我已遵循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。
答案 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;
}