对web系统的支持
毫无疑问,对于spring框架使用最多的还是web系统。对于web系统来说进入认证的最佳入口就是Filter了。spring security不仅实现了认证的逻辑,还通过filter实现了常见的web攻击的防护。
在HttpSecurity对象中,spring security实际提供的是各默认Filter的配置类,通过配置类来控制对应Filter的各个属性配置;在配置完成将Filter加载到HttpSecurity中的FilterChain中去。 默认的Filter并不是在HttpSecurity对象初始化的时候就全部加载,而是根据用户定制情况进行加载 。
常用Filter
下面按照request进入的顺序列举一下常用的Filter:
- ChannelProcessingFilter , 通道选择Filter,确保请求是通过正确的通道过来的,如Http或者Https
- SecurityContextPersistenceFilter,用于将
SecurityContext
放入Session的Filter - UsernamePasswordAuthenticationFilter, 登录认证的Filter,类似的还有CasAuthenticationFilter,BasicAuthenticationFilter等等。在这些Filter中生成用于认证的token,提交到AuthenticationManager,如果认证失败会直接返回。
- RememberMeAuthenticationFilter,通过cookie来实现remember me功能的Filter
- AnonymousAuthenticationFilter,如果一个请求在到达这个filter之前SecurityContext没有初始化,则这个filter会默认生成一个匿名SecurityContext。这在支持匿名用户的系统中非常有用。
- ExceptionTranslationFilter,捕获所有Spring Security抛出的异常,并决定处理方式
- FilterSecurityInterceptor, 权限校验的拦截器,访问的url权限不足时会抛出异常
Filter的顺序
既然用了上面那么多filter,它们在FilterChain中的先后顺序就显得非常重要了。对于每一个系统或者用户自定义的filter,spring security都要求必须指定一个order,用来做排序。对于系统的filter的默认顺序,是在一个FilterComparator
类中定义的,核心实现如下。
FilterComparator() {
int order = 100;
put(ChannelProcessingFilter.class, order);
order += STEP;
put(ConcurrentSessionFilter.class, order);
order += STEP;
put(WebAsyncManagerIntegrationFilter.class, order);
order += STEP;
put(SecurityContextPersistenceFilter.class, order);
order += STEP;
put(HeaderWriterFilter.class, order);
order += STEP;
put(CorsFilter.class, order);
order += STEP;
put(CsrfFilter.class, order);
order += STEP;
put(LogoutFilter.class, order);
order += STEP;
filterToOrder.put(
"org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter",
order);
order += STEP;
put(X509AuthenticationFilter.class, order);
order += STEP;
put(AbstractPreAuthenticatedProcessingFilter.class, order);
order += STEP;
filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter",
order);
order += STEP;
filterToOrder.put(
"org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter",
order);
order += STEP;
put(UsernamePasswordAuthenticationFilter.class, order);
order += STEP;
put(ConcurrentSessionFilter.class, order);
order += STEP;
filterToOrder.put(
"org.springframework.security.openid.OpenIDAuthenticationFilter", order);
order += STEP;
put(DefaultLoginPageGeneratingFilter.class, order);
order += STEP;
put(ConcurrentSessionFilter.class, order);
order += STEP;
put(DigestAuthenticationFilter.class, order);
order += STEP;
put(BasicAuthenticationFilter.class, order);
order += STEP;
put(RequestCacheAwareFilter.class, order);
order += STEP;
put(SecurityContextHolderAwareRequestFilter.class, order);
order += STEP;
put(JaasApiIntegrationFilter.class, order);
order += STEP;
put(RememberMeAuthenticationFilter.class, order);
order += STEP;
put(AnonymousAuthenticationFilter.class, order);
order += STEP;
put(SessionManagementFilter.class, order);
order += STEP;
put(ExceptionTranslationFilter.class, order);
order += STEP;
put(FilterSecurityInterceptor.class, order);
order += STEP;
put(SwitchUserFilter.class, order);
}
上述这些Filter在框架中,有些会默认生效,提供了一些默认配置:
在WebSecurityConfigurerAdapter类中,存在默认的configure方法,它会提供一些默认的权限控制配置,默认方法实现哪下 :
protected void configure(HttpSecurity http) throws Exception {
logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().and()
.httpBasic();
}
同时,在初始化HttpSecurity的方法init中,也会提供一些默认的配置:
protected final HttpSecurity getHttp() throws Exception {
if (http != null) {
return http;
}
DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor
.postProcess(new DefaultAuthenticationEventPublisher());
localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);
AuthenticationManager authenticationManager = authenticationManager();
authenticationBuilder.parentAuthenticationManager(authenticationManager);
Map<Class<? extends Object>, Object> sharedObjects = createSharedObjects();
http = new HttpSecurity(objectPostProcessor, authenticationBuilder,
sharedObjects);
if (!disableDefaults) {
// @formatter:off
http
.csrf().and()
.addFilter(new WebAsyncManagerIntegrationFilter())
.exceptionHandling().and()
.headers().and()
.sessionManagement().and()
.securityContext().and()
.requestCache().and()
.anonymous().and()
.servletApi().and()
.apply(new DefaultLoginPageConfigurer<HttpSecurity>()).and()
.logout();
// @formatter:on
ClassLoader classLoader = this.context.getClassLoader();
List<AbstractHttpConfigurer> defaultHttpConfigurers =
SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);
for(AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
http.apply(configurer);
}
}
configure(http);
return http;
}
通过分析这两个配置处,Security默认加载的Filter清单如下:
1 | Configurer | Filter |
2 | CsrfConfigurer | CsrfFilter |
3 | WebAsyncManagerIntegrationFilter | |
4 | ExceptionHandlingConfigurer | ExceptionTranslationFilter |
5 | HeadersConfigurer | HeaderWriterFilter |
6 | SessionManagementConfigurer | SessionManagementFilter |
7 | RequestCacheConfigurer | RequestCacheAwareFilter |
8 | AnonymousConfigurer | AnonymousAuthenticationFilter |
9 | ServletApiConfigurer | SecurityContextHolderAwareRequestFilter |
10 | DefaultLoginPageConfigurer | DefaultLoginPageGeneratingFilter |
11 | LogoutConfigurer | LogoutFilter |
12 | FormLoginConfigurer | UsernamePasswordAuthenticationFilter |
13 | HttpBasicConfigurer | BasicAuthenticationFilter |
14 |
参考博客:
https://blog.csdn.net/icarusliu/article/details/78722384
https://www.jianshu.com/p/d5ce890c67f7
来源:oschina
链接:https://my.oschina.net/zxh821215/blog/3209501