4

When I create a WebSecurityConfigurerAdapter it is getting registered twice. I've created a configuration exactly the same as the Hello Web Security Java Configuration example from the reference docs.

The configuration is working as expected, though beans and the filter chain gets registered twice as shown in the tomcat output.

00:32:01 INFO : Root WebApplicationContext: initialization started
00:32:01 INFO : Refreshing Root WebApplicationContext: startup date [Thu Oct 09 00:32:01 EST 2014]; root of context hierarchy
00:32:01 INFO : Registering annotated classes: [class com.acme.app.config.SecurityConfig]
______________
00:32:02 INFO : Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@26eed435, org.springframework.security.web.context.SecurityContextPersistenceFilter@cd9947, org.springframework.security.web.header.HeaderWriterFilter@354e8394, org.springframework.security.web.csrf.CsrfFilter@54fb62e3, org.springframework.security.web.authentication.logout.LogoutFilter@1df9cd96, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@4da923c6, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@1ee94efd, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@7d4b5722, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@26dde6a8, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@7c58b660, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@6fd12384, org.springframework.security.web.session.SessionManagementFilter@24d4cc75, org.springframework.security.web.access.ExceptionTranslationFilter@1709e92c, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@2c46f137]
00:32:02 INFO : Root WebApplicationContext: initialization completed in 565 ms
00:32:02 INFO : FrameworkServlet 'dispatcher': initialization started
00:32:02 INFO : Refreshing WebApplicationContext for namespace 'dispatcher-servlet': startup date [Thu Oct 09 00:32:02 EST 2014]; parent: Root WebApplicationContext
00:32:02 INFO : Registering annotated classes: [class com.acme.app.config.WebConfig]
______________
00:32:02 INFO : Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@52b26dcb, org.springframework.security.web.context.SecurityContextPersistenceFilter@10f4b535, org.springframework.security.web.header.HeaderWriterFilter@561ad054, org.springframework.security.web.csrf.CsrfFilter@4b6e4b62, org.springframework.security.web.authentication.logout.LogoutFilter@1d424a71, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@2dad3bf4, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@282a0f5c, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@52eeebb7, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@47d4a88e, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@474c5850, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@6fdc40f8, org.springframework.security.web.session.SessionManagementFilter@2978de23, org.springframework.security.web.access.ExceptionTranslationFilter@5bf190dd, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@22b3fc11]

AppInitializer.java

public class AppInitializer
        extends AbstractAnnotationConfigDispatcherServletInitializer {

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

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

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

}

SecurityConfig.java

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        System.out.println("______________");
        auth
                .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }

}

SecurityWebApplicationInitializer.java

public class SecurityWebApplicationInitializer
        extends AbstractSecurityWebApplicationInitializer {

}

WebConfig.java

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.acme.app")
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**")
                .addResourceLocations("/static/");
    }

    @Bean
    public CookieLocaleResolver getLocaleResolver() {
        CookieLocaleResolver bean = new CookieLocaleResolver();
        bean.setCookieName("clientlanguage");
        bean.setCookieMaxAge(100000);
        return bean;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
        lci.setParamName("lang");
        registry.addInterceptor(lci);
    }

    @Bean
    public TilesConfigurer getTilesConfigurer() {
        CustomTilesInitializer ti = new CustomTilesInitializer();
        TilesConfigurer res = new TilesConfigurer();
        res.setCompleteAutoload(true);
        res.setDefinitions("/WEB-INF/**/tiles.xml");
        return res;
    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.tiles();
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("home");
        registry.addRedirectViewController("/home", "/");
        registry.addViewController("/login").setViewName("login");
        registry.addViewController("/aboutme").setViewName("aboutme");
    }

}

UPDATE

As @lkrnac has pointed out with his answer that the config is being loaded twice during the WebConfig @ComponentScan annotation. I had figured that spring would be smart enough to not load a config that it had previously loaded. I could locate the classes outside of the config namespace though that seems like a nuisance. Instead I have chosen to provide an exclude filter as in the following:

@ComponentScan(basePackages = "com.acme.app",
               excludeFilters = {
                   @Filter(type = ASSIGNABLE_TYPE,
                           value = {
                               WebConfig.class,
                               SecurityConfig.class
                           })
               })

This way I can freely still create new config classes for my web context without having to worry about them being included or not.

4

2 回答 2

4

您的安全配置在 package 中com.acme.app.config.SecurityConfig。这个包被扫描在WebConfig.

所以我怀疑上下文被加载了两次:

  1. 在应用初始化程序中
  2. 通过 WebConfig 中的组件扫描

尝试在包SecurityConfig外定位com.acme.app

于 2014-10-08T14:00:04.457 回答
1

我博客上的匿名用户指出了这个排除替代方案:

@ComponentScan(basePackages = "com.acme.app",
               excludeFilters = {
                  @Filter(type = FilterType.ANNOTATION, value = Configuration.class)
               })
于 2015-01-12T22:47:12.317 回答