spring-security(十七)Filter顺序及简介 博客分类: spring security springsecurity
程序员文章站
2024-03-13 18:53:51
...
前言:
spring security在web应用中是通过各种各样的filter来做认证和安全控制的,由于filter之间的依赖性,过滤器链中filter的顺序也极其重要,不管实际项目中我们选用了哪些过滤器。
1.filter顺序
2.在spring security中是如何保证filter的顺序呢
2.1 简单来说spring是通过FilterComparator类来保证顺序的
在这个类中事先将security中可能会用到的filter顺序定义好,那这个类是如何被调用的呢?
在前面一节(spring-security(十六)Filter配置原理),我们知道spring 安全相关的Filter是在WebSecurity的build方法中调用HttpSecurity的build来将追加到HttpSecurity中filter构建成SecurityFilterChain,再把所有的SecurityFilterChain追加到FilterChainProxy中,最后通过DelegatingFilterProxy注册到ServletContext中的,我们就来看下HttpSecurity的build方法
可以看到,在这个类中构建SecurityFilterChain前会先对filter进行排序,而这个排序类就是FilterComparator,所以不管我们加入到HttpSecurity中的filter顺序是怎样的,spring security最终都会确保我们的Filter是严格按照前面讲述的顺序进行的。具体我们用到的Filter是如何追加到HttpSecurity中的,后续讲具体的Filter时再进行分析。
spring security在web应用中是通过各种各样的filter来做认证和安全控制的,由于filter之间的依赖性,过滤器链中filter的顺序也极其重要,不管实际项目中我们选用了哪些过滤器。
1.filter顺序
- ChannelProcessingFilter,访问协议控制过滤器,可能会将我们重新定向到另外一种协议,如从http转换成https
- SecurityContextPersistenceFilter,用来创建一个SecurityContext并存储在SecurityContextHolder中,因为后续filter需要用SecurityContext存储的认证相关信息,所以需要在请求一开始就要把这些信息设置好,这样也能使在认证过程中对SecurityContext的任何修改都可以保存下来,并在请求结束后存储在HttpSession中(以在下次请求时使用)
- ConcurrentSessionFilter,并发访问控制过滤器,主要做两件事
- UsernamePasswordAuthenticationFilter、CasAuthenticationFilter、BasicAuthenticationFilter等认证对应的filter,经过这些过滤器后SecurityContextHolder中将包含一个完全组装好的Authentication对象,从而使后续鉴权能正常执行
- SecurityContextHolderAwareRequestFilter,用来将ServletRequest封装成能关联到SecurityContextHolder的SecurityContextHolderAwareRequestWrapper(servlet 2.5版本)或者Servlet3SecurityContextHolderAwareRequestWrapper(servlet3.0+版本),从而提供和servlet的集成功能,如调用HttpServletRequest.getUserPrincipal()、HttpServletRequest.authenticate()、HttpServletRequest.login()、HttpServletRequest.logout()等方法
- JaasApiIntegrationFilter,当采用Java Authentication and Authorization Service (JAAS)认证方式时,这个filter用来将SecurityContextHolder中的JaasAuthenticationToken转化成Subject供后续filter使用
- RememberMeAuthenticationFilter,记忆认证处理过滤器,如果前面认证对应的filter没有对当前请求进行处理,并且当前的请求的cookie中有启用RememberMe功能的标识时(默认是cookie中有名称是remember-me的参数,对应的值是1,true,OK),这个filter将对请求进行处理, 从cookie中解析出用户,并进行认证处理,之后在SecurityContextHolder中存入一个Authentication对象。
- AnonymousAuthenticationFilter,匿名认证处理过滤器,如果前面所有的认证处理没有对请求进行认证处理,这个过滤器会向SecurityContextHolder中存入一个匿名的Authentication对象,赋予ROLE_ANONYMOUS的权限,目的是为了在后面的鉴权操作中能始终获取到一个Authentication进行处理,不用考虑null的情况。
- ExceptionTranslationFilter,异常处理过滤器,这个过滤器主要拦截后续过滤器(FilterSecurityInterceptor)操作中抛出的异常,根据异常的类型如AuthenticationException、AccessDeniedException等采取不同的策略,重定向到认证登录页面或重定向到错误页或者直接返回前端一个403码
- FilterSecurityInterceptor 安全拦截过滤器类,获取当前请求url对应的ConfigAttribute,并调用accessDecisionManager进行鉴权处理,如果用户有权执行当前请求就调用真实的处理逻辑,否则抛出相应的异常AuthenticationException、AccessDeniedException。
1.从SessionRegistry中获取SessionInformation来判断session是否过期,如果过期,调用配置好的logout handlers,从而使session无效,并调用SessionInformationExpiredStrategy的onExpiredSessionDetected方法实现重定向或者通知用户session已过期 | |
2.如果没有过期,刷新当前session的LastRequest时间,在多用户同时访问时如果配置了最大并发访问数量,会将LastRequest时间最早的session设置成过期,从而实现并发访问控制 |
2.在spring security中是如何保证filter的顺序呢
2.1 简单来说spring是通过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; put(X509AuthenticationFilter.class, order); order += STEP; put(AbstractPreAuthenticatedProcessingFilter.class, order); order += STEP; filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter", 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); }
在这个类中事先将security中可能会用到的filter顺序定义好,那这个类是如何被调用的呢?
在前面一节(spring-security(十六)Filter配置原理),我们知道spring 安全相关的Filter是在WebSecurity的build方法中调用HttpSecurity的build来将追加到HttpSecurity中filter构建成SecurityFilterChain,再把所有的SecurityFilterChain追加到FilterChainProxy中,最后通过DelegatingFilterProxy注册到ServletContext中的,我们就来看下HttpSecurity的build方法
@Override protected DefaultSecurityFilterChain performBuild() throws Exception { Collections.sort(filters, comparator); return new DefaultSecurityFilterChain(requestMatcher, filters); }
可以看到,在这个类中构建SecurityFilterChain前会先对filter进行排序,而这个排序类就是FilterComparator,所以不管我们加入到HttpSecurity中的filter顺序是怎样的,spring security最终都会确保我们的Filter是严格按照前面讲述的顺序进行的。具体我们用到的Filter是如何追加到HttpSecurity中的,后续讲具体的Filter时再进行分析。