How to implement Spring Security 4 with XML and Java config

advertisements

I am trying to implement Spring-Security 4 into my Spring MVC web and rest app. I added 2 classes to enable Spring Security the java config way. I still want to hold onto my web.xml and not change the entire project to use java config. As soon as I do that, I get the following error:

29-May-2015 08:47:12.826 SEVERE [localhost-startStop-1]
org.apache.catalina.core.StandardContext.filterStart Exception starting
filter springSecurityFilterChain
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean
named 'springSecurityFilterChain' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.
getBeanDefinition(DefaultListableBeanFactory.java:687)

As you can see, it says that the springSecurityFilterChain cannot be recognized. This is of course supposed to be enabled by the @EnableWebSecurity as you see below:

Classes used for Spring Security:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  auth.inMemoryAuthentication().withUser("abc").password("123456").roles("USER");
  auth.inMemoryAuthentication().withUser("admin").password("123456").roles("ADMIN");
  auth.inMemoryAuthentication().withUser("dba").password("123456").roles("DBA");
}

@Override
protected void configure(HttpSecurity http) throws Exception {

  http.authorizeRequests()
    .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
    .antMatchers("/dba/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_DBA')")
    .and().formLogin();

    }
}

public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
   //do nothing
}

The weird thing is if I add the springSecurityFilterChain to my web.xml, at runtime it complains and says there is a duplicate springSecurityFilterChain. I noticed that ultimately in the Java config, they do this:

public class MvcWebApplicationInitializer extends
    AbstractAnnotationConfigDispatcherServletInitializer {

@Override
protected Class<?>[] getRootConfigClasses() {
    return new Class[] { SecurityConfig.class };
}

Where they register the SecurityConfig with the Java config for the MvcWebApp. This basically makes it part of the servlet context I believe.

All in all, how can I have my springSecurityFilterChain recognized? Do I need to register my SecurityConfig class in web.xml or the existing application context?

I think this may be the first problem area:

public class SecurityWebApplicationInitializer
  extends AbstractSecurityWebApplicationInitializer {

}

The spring docs say:

Instead, we should register Spring Security with the existing ApplicationContext. For example, if we were using Spring MVC our SecurityWebApplicationInitializer.

Can this mean in my case, I can take SecurityConfig and should make it a bean? Or is it not already a bean because it is dicoverable through @Configuration?

How can I make SecurityConfig recognized via XML while using the new Java config as well?


Assuming what you want is to get Spring Security Java Config working with only 2 classes SecurityConfig and SecurityWebApplicationInitializer, you need to do the following to get it working. Please note that I am assuming that your spring mvc configuration is still XML. Please note that com.mkyong.web.config package will have the SecurityConfigclass. This will ensure that the web context will have your security configuration available.

Web.xml as follows

<context-param>
          <param-name>contextClass</param-name>
          <param-value>
              org.springframework.web.context.support.AnnotationConfigWebApplicationContext
          </param-value>
      </context-param>
      <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>com.mkyong.web.config</param-value>
      </context-param>

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