无法使用JavaConfig配置两个HttpSecurity设置

时间:2014-06-30 11:18:37

标签: java spring spring-security

我已遵循official documentation中有关如何配置两个单独的HttpSecurity个实例的建议:

@Configuration
@EnableWebSecurity
public class SoWebSecurityConfig
{
  @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(username -> {
      log.info("\n\n\n *********  authenticating {} ************************************\n\n\n", username);
      return new User(username, "", asList(new SimpleGrantedAuthority("TV")));
    });
  }

  @Configuration
  @Order(1)
  public static class SwiperSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception { configureHttpSec(http, "/swiper"); }
  }

  @Configuration
  @Order(2)
  public static class TvSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception { configureHttpSec(http, "/tv"); }
  }

  static HttpSecurity configureHttpSec(HttpSecurity http, String urlBase) throws Exception {
    http   .csrf().disable()
           .exceptionHandling().authenticationEntryPoint(new Http403ForbiddenEntryPoint())
    .and() .authorizeRequests().antMatchers(urlBase+"/**").authenticated()
    .and() .httpBasic()
    .and() .logout().logoutUrl(urlBase+"/logout").logoutSuccessHandler((req,resp,auth) -> {})
    ;
    return http;
  }
}

在日志中,我确实看到了两个过滤链:

2014-06-30 12:44:22 main INFO  o.s.s.w.DefaultSecurityFilterChain - Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.request.as
ync.WebAsyncManagerIntegrationFilter@806996, org.springframework.security.web.context.SecurityContextPersistenceFilter@1937eaff, org.springframework.security.web.header.HeaderWriterFilter@71e4b308, org.springfr
amework.security.web.authentication.logout.LogoutFilter@1d1cbd0f, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@9b9a327, org.springframework.security.web.savedrequest.RequestCach
eAwareFilter@4993febc, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@67064bdc, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@78b612c6, org.s
pringframework.security.web.session.SessionManagementFilter@6d11ceef, org.springframework.security.web.access.ExceptionTranslationFilter@6e7c351d, org.springframework.security.web.access.intercept.FilterSecurit
yInterceptor@571a01f9] 
2014-06-30 12:44:22 main INFO  o.s.s.w.DefaultSecurityFilterChain - Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.request.as
ync.WebAsyncManagerIntegrationFilter@30c1da48, org.springframework.security.web.context.SecurityContextPersistenceFilter@427ae189, org.springframework.security.web.header.HeaderWriterFilter@4784efd9, org.spring
framework.security.web.authentication.logout.LogoutFilter@187e5235, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@514de325, org.springframework.security.web.savedrequest.RequestC
acheAwareFilter@16a9eb2e, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@76332405, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@43a65cd8, or
g.springframework.security.web.session.SessionManagementFilter@3fba233d, org.springframework.security.web.access.ExceptionTranslationFilter@376c7d7d, org.springframework.security.web.access.intercept.FilterSecu
rityInterceptor@3b48e183] 

但只有我用Order(1)指定的那个才会被使用;与另一个匹配的网址将不会通过身份验证。

我也尝试过更密切地关注文档,使用anyRequest()而不是@Order(2)配置的蚂蚁匹配器,但结果是相同的。

有什么方法可以解决这个问题?

我正在使用Spring 4.0.5,Spring Security 3.2.4。

1 个答案:

答案 0 :(得分:4)

您未能在一个关键方面遵循文档。

http.authorizeRequests().antMatchers(urlBase+"/**").authenticated()

表示您将此HttpSecurity注册为全局安全模块,该模块适用于所有 URL,但仅需要对使用Ant匹配器选择的那些进行身份验证。当您执行此操作两次时,最终会得到两个链式全局安全模块,因此当然只有第一个模块负责所有URL。

文档反而建议:

http.antMatcher(urlBase+"/**").authorizeRequests().anyRequest().authenticated()

这意味着Ant匹配器将用于选择此安全模块负责的URL,并绕过所有其他URL。通过这种方式,第二个模块可以在适当的时候获得机会。

因此,您只需稍微调整静态配置器方法即可:

  static HttpSecurity configureHttpSec(HttpSecurity http, String urlBase) throws Exception {
    http   .csrf().disable()
           .exceptionHandling().authenticationEntryPoint(new Http403ForbiddenEntryPoint())
    .and() .antMatchers(urlBase+"/**").authorizeRequests().anyRequest().authenticated()
    .and() .httpBasic()
    .and() .logout().logoutUrl(urlBase+"/logout").logoutSuccessHandler((req,resp,auth) -> {})
    ;
    return http;
  }