DelegatingFilterProxy源码分析
说明该方法会在DelegatingFilterProxy初始化的时候调用,目的是创建一个链式调用的Filter类型是FilterChainProxy该类实际上是Filter的一个实现类。
FilterChainProxy源码分析
FilterInvocation是Spring的一个不同的Bean该方方法中实际上就上将ServletRequest和ServletResponse转换为HttpServletRequest和HttpServletResponse。
重点看一下getFilters方法。
如果该请求下没有相应的Security过滤器,就直接放行
创建一个VertualFilterChain该Chain作为FilterChain下的一个子Chain主要是实现SpringSecurity相关Filter的链式调用。
接下来看看VertualFilterChain的doFilter调用代码:
调用VirtualFilterChain的doFilter方法,调用参数参数链式调用。
核心过滤器介绍
SecurityContextPersistenceFilter
该Filter主要是通过SecurityContext作为SpringSecurity执行的上下文,这里一般会保存用的的登录的Authentication信息。而且SpringSecurity会在请求路由的时候将SecurityContext作为HttpSession的一个命名属性存储。同样SpringSecurty会通过SecurityContextHolder类来方便的获取SecurityContext里面的信息。在每一次请求结束的时候,该filter负责清空SecurityContextHolder里面的内容。SpringSecurity建议为了安全考虑,不建议用户直接的去访问HttpSession。最简单直接的做法就是直接操作SecurityContextHolder类。
注意:这里如果在多个request并发访问的时候,会出现多个Request中从Session获取的是同一个SecurityContext,此时可能会出现一个SecurityContext被多个线程共同访问。此时为了避免多线程之间由于访问的一个session获取的同一个SecurityContext修改造成的影响,建议用户可以自己创建一个使用SecurityContextHolder的createEmptyContext方法创建一个新的临时的对象为每一个请求。并且将用户的认证信息存储到SecurityContext中,这样就不会影响其他线程中的数据了。
UsernamePasswordAuthenticationFilter
这个Filter是最常见并且需要定制的Filter之一。通常需要用户覆盖率比较高。该Filter在SecurityContextPersistentFilter之后被调用。该Filter继承自AbstractAuthenticationProcessingFilter。一般在继承AbstractAuthenticationProcessingFilter的时候只需要覆盖其attemptAuthentication方法。下面看看源码分析
看看该方法内部实现:
如果是登陆认证URl就执行
填充用户登录认证信息代码:
该Filter获取ProviderManager该类负责查询用户的DB信息以及角色相关信息并返回
Authentication对象。下面看一下ProviderManager对象的authenticate方法。
查看DAOAuthenticationProvider方法:
查看UserDetailService#loadUserbyName方法
DAOAuthenticationProvider调用UserService结束后需要对用户的状态做校验