SpringSceurity源码分析
当我们在web.xml文件中配置过滤器链时
<filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter>
filter会通过org.springframework.web.filter.DelegatingFilterProxy创建对象,我们点进去这个类
public class DelegatingFilterProxy extends GenericFilterBean {...}
public DelegatingFilterProxy() { }
使用无参构造创建了DelegatingFilterProxy代理对象,为什么是代理对象呢,我们后面见分晓!
我们还发现它继承了GenericFilterBean我们再点进去
public abstract class GenericFilterBean implements Filter, BeanNameAware, EnvironmentAware,EnvironmentCapable, ServletContextAware, InitializingBean, DisposableBean {...}
最终我们发现它实现了Filter接口,这个Filter就是我们熟知的servlet.Filter 当对象创建成功就会执行init方法,(default 在java8以后,接口中可以添加使用default或者static修饰的方法,在这里我们只讨论default方法,default修饰方法只能在接口中使用,在接口中被default标记的方法为普通方法,可以直接写方法体,实现类会继承接口中的default方法。)
default public void init(FilterConfig filterConfig) throws ServletException {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; default public void destroy() {} }
在GenericFilterBean中确实继承继承了init方法
@Override public final void init(FilterConfig filterConfig) throws ServletException { Assert.notNull(filterConfig, "FilterConfig must not be null"); this.filterConfig = filterConfig; // Set bean properties from init parameters. PropertyValues pvs = new FilterConfigPropertyValues(filterConfig, this.requiredProperties); if (!pvs.isEmpty()) { try { BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); ResourceLoader resourceLoader = new ServletContextResourceLoader(filterConfig.getServletContext()); Environment env = this.environment; if (env == null) { env = new StandardServletEnvironment(); } bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, env)); initBeanWrapper(bw); bw.setPropertyValues(pvs, true); } catch (BeansException ex) { String msg = "Failed to set bean properties on filter '" + filterConfig.getFilterName() + "': " + ex.getMessage(); logger.error(msg, ex); throw new NestedServletException(msg, ex); } } // Let subclasses do whatever initialization they like. initFilterBean(); if (logger.isDebugEnabled()) { logger.debug("Filter '" + filterConfig.getFilterName() + "' configured for use"); } }
在这个方法中有一个initFilterBean()方法
我们发现他在DelegatingFilterProxy重写了该方法我们debug过去跟踪
发现这个wac就是我们的webApplicationContext对象,进行了initDelegate方法
这里的targetBeanName 就是我们写在xml配置文件中的名字!是不能改变的。
我们又发现这个方法最终得到了一个FilterChainProxy对象 它里面就是维护了很多拦截器对象
[Filter Chains: [[ any request, [org.springframework.security.web.context.SecurityContextPersistenceFilter@4c1c8384, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@1a2d81cd, org.springframework.security.web.header.HeaderWriterFilter@712dde98, org.springframework.security.web.csrf.CsrfFilter@72e81ed5, org.springframework.security.web.authentication.logout.LogoutFilter@5ac0b3af, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@2c1572d3, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@33d3a0d7, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@1ff1ece, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@5efd9895, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@5979ea73, org.springframework.security.web.session.SessionManagementFilter@77823c93, org.springframework.security.web.access.ExceptionTranslationFilter@ef245c3, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@3cf95db8]]]]
我们点开这个FilterChainProxy对象进行查看 会发现它维护了一个private List<SecurityFilterChain> filterChains;集合
我们先来看看这个doFilte方法
发现无论如何都会进入这个doFilterInternal(request, response, chain);方法 debug进行查看
这里的13 就是拦截器的个数,当然我自己配置了登录页面和退出登录页面所以没得
下面我们就来逐个分析这些拦截器的作用
1.SecurityContextPersistenceFilter
org.springframework.security.web.context.SecurityContextPersistenceFilter
首当其冲的一个拦截器,非常重要主要的是使用SecurityContextReposiyory在session中保存或者更新一个SecurityContext,并将SecurityContext给以后的过滤器使用,来为后续filter建立所需的上下文,SecurityContext中存储了当前用户的认证和权限信息。
2.WebAsyncManagerIntegrationFilter
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter
此过滤器用于继承SercurityContext到Spring异步执行机制中的WebAsyncManager,和spring整合必须的。
3.HeaderWriterFilter
org.springframework.security.web.header.HeaderWriterFilter
向情求得header中添加响应得信息,可以在http变迁内部使用security:headers来控制
4.CsrfFilter
org.springframework.security.web.csrf.CsrfFilter
csrf又称跨域请求伪造,SpringSecurity会对所有得post请求验证是否包含系统生成得csrf得token信息,如果不包含,则报错,起到防止csrf攻击得效果。
5.LogoutFilter
org.springframework.security.web.authentication.logout.LogoutFilter
匹配URL为/logout的请求,实现用户退出,清除认证信息。
6.UsernamePasswordAuthenticationFilter
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
认证操作得过滤器,默认匹配URL为/login且必须为POST请求。
7.DefaultLoginPageGeneratingFilter
org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter
如果没有在配置文件中指定认证页面,则该过滤器会自动生成一个认证页面
8.DefaultLogoutPageGeneratingFilter
org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter
生成一个默认得退出登录页面,也无卵用
9.BasicAuthenticationFilter
org.springframework.security.web.authentication.www.BasicAuthenticationFilter
此过滤器会自动解析HTTP请求中头部名字为Authentication,且以Basic开头的头信息。
10.RequestCacheAwareFilter
org.springframework.security.web.savedrequest.RequestCacheAwareFilter
这个filter的用途官方解释是 用于用户登录成功后,重新恢复因为登录被打断的请求,就是用于记住登录得
11.SecurityContextHolderAwareRequestFilter
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter
针对ServletRequest进行一次包装,使得request具有更加丰富得API
12.AnonymousAuthenticationFilter
org.springframework.security.web.authentication.AnonymousAuthenticationFilter
当SecurityContextHolder中认证信息为空,则会创建一个匿名得用户存入到SecurityContextHolder中,spring security为了兼容未登录得访问,也走了一套认证流程,只不过是个匿名得身份。
13.SessionManagementFilter
org.springframework.security.web.session.SessionManagementFilter
SecurityContextRepository限制同一用户多个会话得数量
14.ExceptionTranslationFilter
org.springframework.security.web.access.ExceptionTranslationFilter
异常转换锅炉其文娱整个springSecurityFilterChain得后方,用来转换整个链路中出现得异常
15.FilterSecurityInterceptor
org.springframework.security.web.access.intercept.FilterSecurityInterceptor
获取所配置资源访问得授权信息,根据SecurityContextHolder中存储得用户信息来决定其是否有权限。
那么,是不是spring security一共就这么多过滤器呢?答案是否定的!随着spring-security.xml配置的添加,还会出现新的过滤器。 那么,是不是spring security每次都会加载这些过滤器呢?答案也是否定的!随着spring-security.xml配置的修改,有些过滤器可能会被去掉。
终于写完了!!!沃日!!!真是太多了!
全部评论
(0) 回帖