首页 > SpringSceurity源码分析
头像
社交牛逼一号
发布于 2021-09-02 23:18
+ 关注

SpringSceurity源码分析

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 就是拦截器的个数,当然我自己配置了登录页面和退出登录页面所以没得


总结:通过上面的代码分析,SpringSecurity中要使用到的过滤器最终都保存在了DefaultSecurityFilterChain对象的List filter对象中。
当然可能分析的不清楚,我们画个图就一目了然啦!!

下面我们就来逐个分析这些拦截器的作用

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) 回帖
加载中...
话题 回帖

相关热帖

热门推荐