4

我正在尝试让 Spring SecuirtyConfig 与 Spring MVC 和 JavaConfig 一起使用,但出现以下错误:

java.lang.IllegalStateException:未找到 WebApplicationContext:未注册 ContextLoaderListener?org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:251)

这是我的 SampleSimpleWebSecurityConfig:

@Configuration
@EnableWebSecurity
public class SampleSimpleWebSecurityConfig extends SimpleWebSecurityConfig {

    private static final Logger logger = LoggerFactory.getLogger(SampleSimpleWebSecurityConfig.class);

    protected void authorizeUrls(ExpressionUrlAuthorizationRegistry interceptUrls) {

        logger.warn("* * Loadinging Role(s) * *");
        interceptUrls
                .antMatchers("/*").permitAll()
                .antMatchers("/ask-union").hasRole("ROLE_VERIFIED_MEMBER");
    }

    protected void configure(
            SecurityFilterChainSecurityBuilder springSecurityFilterChain) throws Exception {
        springSecurityFilterChain
                .formLogin()
                .permitAll();
    }

    protected void registerAuthentication(AuthenticationRegistry registry) throws Exception {
        registry
                .inMemoryAuthentication()
                .withUser("xxxx@aol.com.dev").password("testing").roles("ROLE_VERIFIED_MEMBER").and();

    }
}

这是我的 web.xml:

 <servlet>
    <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>org.xxxx.inquiryconfig</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>securityFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>org.xxxx.inquiryconfig.SampleSimpleWebSecurityConfig</param-name>
        <param-value>springSecurityFilterChain</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>securityFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

我的旧 Spring Secuiryt XML:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                        http://www.springframework.org/schema/security
                        http://www.springframework.org/schema/security/spring-security-3.1.xsd">


    <global-method-security pre-post-annotations="enabled" />

    <http use-expressions="true">
        <intercept-url access="hasRole('ROLE_VERIFIED_MEMBER')" pattern="/ask**" />
        <intercept-url pattern='/*' access='permitAll' />
        <form-login default-target-url="/visit" />

        <logout logout-success-url="/" />
    </http>

    <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="XXXX@aol.com.dev" password="testing" authorities="ROLE_VERIFIED_MEMBER" />
            </user-service>

        </authentication-provider>
    </authentication-manager>
</beans:beans>
4

2 回答 2

4

您的错误指出:

java.lang.IllegalStateException:未找到 WebApplicationContext:未注册 ContextLoaderListener?org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:251)

ContextLoaderListener因此,只需在您的 web.xml 中,在过滤器和 servlet 之前注册一个。

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

对于applicationContext,在您的 web.xml 中添加一个上下文参数

<context-param>
    <param-name>contextClass</param-name>
    <param-value>com.yourcompany.yourclass</param-value>
</context-param>

com.yourcompany.yourclass您的应用程序上下文配置类在哪里。

一个典型的 Spring MVC 应用程序有 2 个上下文,应用程序上下文和 servlet 上下文,其中应用程序是根或父级,而 servlet 上下文是它的子级。ContextLoaderListener 侦听应用程序上下文,默认情况下会在其中找到它,/WEB-INF/applicationContext.xml这就是 Spring 在那里寻找它但找不到它的原因。我假设您使用的是 java@Configuration类,所以将其指向该类。

于 2013-03-20T17:49:16.210 回答
2

Sotirios 基本上是正确的。正如他所提到的,父母和孩子有两种不同的配置。我在下面发布的配置的变体可以在samples/social/src/main/webapp/WEB-INF/web.xml中找到(即演示 Spring Security Java Config with Spring Social)。

Spring Security 通常在父上下文中配置。要在 web.xml 中使用 Java 配置,您可以执行以下操作:

<!-- Java-based Spring container definition -->
<context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>

<!-- Location of Java @Configuration classes that configure the components that makeup this application -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>org.xxxx.inquiryconfig.SampleSimpleWebSecurityConfig</param-value>
</context-param>

<listener>
    <listener-class>
      org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

<!-- use the springSecurityFilterChain -->
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <!-- NOTE This does not specify its own configuration it is
         loaded by the ContextLoaderListener instead -->

    <!-- NOTE by default the filter name is used to
         look up the Spring Security Filter Chain if you like you
         can use any filter name you want, but you must specify
         the bean name instead in this instance. Since we use the
         springSecurityFilterChain as the filter name this is not
         necessary
    <init-param>
        <param-name>targetBeanName</param-name>
        <param-value>springSecurityFilterChain</param-value>
    </init-param> -->
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

重要的是 Spring MVC 配置和父上下文不重叠,否则您将创建重复的对象(即一个在父级中,一个在子级中)。具体来说,您需要确保 DispatcherServlet 的 contextConfigLocation 不会加载与 ContextLoaderListener 的 contextConfigLocation 相同的类。

更新:

您还需要确保以正确的顺序指定 URL。现在的问题是 /* 与 /ask-union 匹配的 URL 相同。请记住,每种模式都是按顺序尝试的。这意味着您应该如下所示更新您的配置,以便达到 ask-union。您还想删除“ROLE_”部分,因为 hasRole 会自动将 ROLE_ 前缀放入其中。

    interceptUrls
            .antMatchers("/ask-union").hasRole("VERIFIED_MEMBER")
            .antMatchers("/*").permitAll();
于 2013-03-20T21:18:41.257 回答