6

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?

eis
  • 51,991
  • 13
  • 150
  • 199
logixplayer
  • 939
  • 2
  • 13
  • 23
  • I am not able to replicate the exact same problem mentioned by you, However the changes below is working for me when I am trying. In case you have already done as per answer then please post your web.xml as well as your mvc config – ArunM Jun 01 '15 at 12:00

3 Answers3

3

Thanks to ArunM, I revisited my issue and now have an XML and Java config combination. Spring MVC and the web app does use web.xml and default-servlet.xml PLUS a java config app class that imports Spring Security.

@Configuration
@Import({ SecurityConfig.class})
@ImportResource( {"classpath:web-context.xml",
   "classpath:service-context.xml","classpath:data-context.xml"})
public class AppConfig {
   public AppConfig() {
      super();
   }
}

I use the @Import annotation to import the Spring Security SecurityConfig class.

I also do my contextConfigLocation scanning for all my context files via annotation: @ImportResource.

The trick was not to load SecurityConfig via the contextConfigLocation BUT create an AppConfig class that sets up the app context by including everything in it together.

eis
  • 51,991
  • 13
  • 150
  • 199
logixplayer
  • 939
  • 2
  • 13
  • 23
  • where do you add the AppConfig class? Do you have an example? I'm having problems getting the context xmls to work after importing them. Its like they don't exist – Abu Sulaiman Aug 07 '17 at 20:32
2

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>
ArunM
  • 2,274
  • 3
  • 25
  • 47
  • Hi ArunM, my contextConfigLocation contains my XML context files. I have chained a couple of modules together, i.e. web-context.xml, service-context.xml, data-context.xml. I can't combine my XML files and the SecurityConfig class together, it gives an error: BeanDefinitionStoreException: IOException parsing XML document from ServletContext resource [/ca.abc.web.security]; I have been stuck on this for 5 days now. I am trying various combinations. It seems like @EnableWebSecurity in my SecurityConfig is not being picked up even when I somehow got it to load error free. – logixplayer Jun 01 '15 at 15:38
  • I have also tried loading it just with SecurityConfig and not SecurityWebApplicationInitializer. Instead of SecurityWebApplicationInitializer, I have also tried to define it in web.xml via springSecurityFilterChain in a filter. It still doesn't work though. I have also tried using other Spring Security jars like spring-security-javaconfig, At times it ran without error but Spring Security never was picked up. No URL;s were ever prompted for a login. – logixplayer Jun 01 '15 at 15:45
  • I still think the problem is that your SecurityConfig is not part of your 'WebApplicationContext'. The easiest way to verfiy this is to start up and check the list of beans from the logs in a properly working spring security application and then compare with your application – ArunM Jun 01 '15 at 19:15
  • I suggest that you follow the approach here http://stackoverflow.com/questions/19365366/mixing-xml-and-java-config-with-spring and mix both Java and XML Config by using importResource – ArunM Jun 01 '15 at 19:15
  • ArunM, unfortunately I wasnt able to configure my SecurityConfig as you suggested. I tried importing my other context files into SecurityConfig & that didn't work. I also feel that this is not the right approach to include context files with my SecurityConfig. I see that you can configure Spring via java config and that is where you put your context files but to me putting everything in java is also over kill. I found this link that enables Spring Security with web.xml but it also doesn't have any other context files: http://www.baeldung.com/spring-security-login. Might have to resort to xml. – logixplayer Jun 02 '15 at 17:24
0

Add the following line in your spring-context.xml:

<!-- to activate annotations in beans already registered in the application context -->
<context:annotation-config />

and then can add the bean definition for the security config.

<bean name="SecurityConfig" class="com.config.security.SecurityConfig" />
Parth Kansara
  • 189
  • 1
  • 11