4

I am trying to get Spring SecuirtyConfig working with Spring MVC and JavaConfig and I am getting the following error:

java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered? org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:251)

Here is my 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();

    }
}

Here is my 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>

My old 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>
SJS
  • 5,607
  • 19
  • 78
  • 105
  • 1
    It looks to me like you are trying to port everything from XML to java. Look into using `SpringServletContainerInitializer` and a `WebApplicationInitializer` to replace your `web.xml` – Sotirios Delimanolis Mar 20 '13 at 17:52

2 Answers2

4

Your error states:

java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered? org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:251)

So just register a ContextLoaderListener in your web.xml, before filters and servlets.

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

For the applicationContext, add a context parameter in your web.xml

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

where com.yourcompany.yourclass is your application context configuration class.

A typical Spring MVC application has 2 contexts, the application context and the servlet context, where the application is the root or parent and the servlet context is its child. A ContextLoaderListener listens for the application context, which by default is found in /WEB-INF/applicationContext.xml which is why Spring is looking for it there, but can't find it. I'm assuming you are using a java @Configuration class, so point it to that class.

Grzegorz Rożniecki
  • 27,415
  • 11
  • 90
  • 112
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • 1
    that did not work.. once I did that I got this error. Could not open ServletContext resource [/WEB-INF/applicationContext.xml – SJS Mar 20 '13 at 19:04
  • Can you update what your `web.xml` and `@Configuraton` classes look like and show specific errors? – Sotirios Delimanolis Mar 21 '13 at 13:13
  • Hi there @SotiriosDelimanolis , I have a similar problem and I can't figure it out, will you be able to take a look? thanks. http://stackoverflow.com/questions/19826228/spring-web-security-web-xml-mvc-dispatcher-bean-is-created-twice – Jaxox Nov 07 '13 at 19:58
  • @SotiriosDelimanolis I have a problem that is very similar to this one. Are you willing to give me a hand with it? I need another perspective on it. Here is the link: http://stackoverflow.com/questions/22643577/adding-security-to-spring-petclinic – CodeMed Mar 26 '14 at 00:29
  • @CodeMed I've never worked with Spring Security before, sorry. – Sotirios Delimanolis Mar 26 '14 at 00:32
  • @SotiriosDelimanolis I think the problem is with a failure to recognize the distinction between the `application context` and the `servlet context`, which you describe in your answer above. Specifically in the way the petclinic app uses `clinicservice` and `xml config` files. I think the solution is in knowing the syntax for the `xml config` files that petclinic employs. Are you willing to take a look at my restated problem? Here is the link to a new question: http://stackoverflow.com/questions/22670646/where-do-i-define-springsecurityfilterchain-bean – CodeMed Mar 26 '14 at 19:11
2

Sotirios got this mostly correct. As he mentioned there are two different configurations a parent and a child. A variation of the configuration I am posting below can be found in the samples/social/src/main/webapp/WEB-INF/web.xml (i.e. demo Spring Security Java Config with Spring Social).

Spring Security is typically configured in the parent context. To do so with Java Configuration in the web.xml you can do something like this:

<!-- 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>

It is important that the Spring MVC configuration and the parent context do not overlap otherwise you will have duplicate objects created (i.e. one in the parent and one in the child). Specifically you will want to ensure that the DispatcherServlet's contextConfigLocation does not load the same classes as the ContextLoaderListener's contextConfigLocation.

Update:

You also need to ensure your URLs are specified in the correct order. The problem right now is that /* matches the same URLs that /ask-union does. Remember each pattern is tried in order. This means you should update your configuration as shown below so that ask-union is reached. You also want to remove the "ROLE_" portion since hasRole automatically puts the ROLE_ prefix in.

    interceptUrls
            .antMatchers("/ask-union").hasRole("VERIFIED_MEMBER")
            .antMatchers("/*").permitAll();
Rob Winch
  • 21,440
  • 2
  • 59
  • 76
  • I inserted your code and I am still getting... java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered? org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:251) – SJS Mar 21 '13 at 12:32
  • I added org.springframework.web.context.ContextLoaderListener and no error, no login screen and no working... – SJS Mar 21 '13 at 12:47
  • Did you ensure that you specified the and that it is the first ? Also switch the ordering of your intercept URLs as the second pattern will never be reached (remember just as with the order matters). Also update your hasRole. I gave an update that demonstrates both updates. – Rob Winch Mar 21 '13 at 15:43
  • You might also elaborate on what you mean by " no login screen and and no working"....what are you doing, how is it not working? I'd try to access your /ask-union page which should send you to the /login URL (you will need a login page a that place). Then your login page should POST to /login a username and password with the parameters username and password respectively. – Rob Winch Mar 21 '13 at 22:53
  • @RobWinch I have a similar problem. The EDIT is the part that is similar. Are you willing to help me with it? Here is the link: http://stackoverflow.com/questions/22643577/adding-security-to-spring-petclinic – CodeMed Mar 26 '14 at 00:58