Spring Security源码分析

Spring Security是一套访问控制的框架,主要的功能是验证和授权。

一、整体设计

从官方文档了解Spring Security的架构设计,Spring Security支持Servlet和WebFlux。

SpringSecurity 本质是一个过滤器链,从启动开始可以获取到的过滤器链包括:

org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilterorg.springframework.security.web.context.SecurityContextPersistenceFilter org.springframework.security.web.header.HeaderWriterFilter org.springframework.security.web.csrf.CsrfFilter org.springframework.security.web.authentication.logout.LogoutFilter org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter org.springframework.security.web.savedrequest.RequestCacheAwareFilter org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter org.springframework.security.web.authentication.AnonymousAuthenticationFilter org.springframework.security.web.session.SessionManagementFilter org.springframework.security.web.access.ExceptionTranslationFilter org.springframework.security.web.access.intercept.FilterSecurityInterceptor

从官网中选取最具代表性的一张架构设计图,可以清晰的看到客户端发送的请求,需要经过一系列的过滤器后才能执行真正的Servlet方法,Spring Security就是过滤器链中的其中一环。根据官方介绍,Spring Security中主要有2个类和1个接口,分别是DetegatingFilterProxy、FilterChainProxy和SecurityFilterChain。 Spring Security的运行流程主要是由DetegatingFilterProxy进行分派,真正要执行的过滤器链由FilterChainProxy进行代理。在容器启动的时候,通过@Bean注解会在IOC容器里面创建SpringSecurityFilterChain,而SpringSecurityFilterChain其本质就是FilterChainProxy对象。在创建SpringSecurityFilterChain时,会通过FilterChainProxy的有参构造器注入默认的DefaultSecurityFilterChain和调用SecurityFilterChainBuilder的build方法生成的DefaultSecurityFilterChain。默认的DefaultSecurityFilterChain中没有任何过滤器,但是调用SecurityFilterChainBuilder的build方法生成的DefaultSecurityFilterChain里面就会注入Spring Security的一系列默认的过滤器。SecurityFilterChain是一个接口,接口里面定义了 matches方法和getFilters方法。FilterChainProxy执行过滤的时候会先调用SecurityFilterChain的matches方法,看是否满足匹配条件,如果不满足就继续下一个SecurityFilterChain。如果满足匹配条件,就会调用getFilters方法来获取到注册的过滤器,然后执行过滤器的doFilter方法进行过滤。

过滤成功和失败都提供了回调的接口,可以自定义实现,

二、运行流程 1、DetegatingFilterProxy创建

Servlet容器初始化,会创建了DelegatingFilterProxy。WebApplicationInitializer接口的onStartup方法将会在Servlet容器启动时被调用,AbstractSecurityWebApplicationInitializer实现了该接口,因此AbstractSecurityWebApplicationInitializer的onStartup方法将被调用。在onStartup方法中,有一个insertSpringSecurityFilterChain方法。 可以看到在insertSpringSecurityFilterChain方法中创建了DelegatingFilterProxy对象,并将DelegatingFilterProxy对象添加到了Servlet的过滤器链中。进入DelegatingFilterProxy的构造器可以看到将DelegatingFilterProxy的成员变量targetBeanName赋值成了DEFAULT_FILTER_NAME,即springSecurityFilterChain。

2、DelegatingFilterProxy分派任务

DelegatingFilterProxy被创建后加入到了Servlet容器的过滤器链中,并且作为第一个过滤器,因此DelegatingFilterProxy的doFilter方法将在用户发起请求后被调用。 在doFilter方法中会执行initDelegate 和invokeDelegate方法

通过上述代码可以看出 DelegatingFilterProxy将真正的过滤操作分派给了delegateToUse这个局部变量。继续查看源码,看delegateToUse是什么。 可以看到delegateToUse是从WebApplicationContext里面根据BeanName获取到的,而targetBeanName在之前已经设置为springSecurityFilterChain。

因此,DelegatingFilterProxy其实就是将真正的过滤操作转派给了一个BeanName为springSecurityFilterChain的对象。

接下来我们的问题就变成了BeanName为springSecurityFilterChain的对象是什么。 在WebSecurityConfiguration这个配置类中,创建了springSecurityFilterChain。那这个对象到底是什么呢,带着这个疑问继续看源码是如何创建springSecurityFilterChain对象并返回的。

可以看到这个方法先是调用了apply方法,然后调用build方法返回了创建的对象。

可以看到apply方法主要是将形参configurer放到了this.configurers这个map里面,而这个configurer就是前面传进来的实参WebSecurityConfigurerAdapter对象。这个对象在build的调用链中的configure()方法中会被使用,主要用于调用configure(WebSecurity web)方法,这个后续章节再做介绍。

调用build方法的是WebSecurity类的对象,通过泛型的比对可以发现build方法的返回值类型为Filter,因此必定是调用WebSecurity的performBuild方法。

可以清楚的看到返回的Filter其实就是FilterChainProxy对象,所以springSecurityFilterChain对象其本质就是FilterChainProxy对象。因此,DelegatingFilterProxy将真正的过滤操作转派给了一个BeanName为springSecurityFilterChain的对象,就是转派给了FilterChainProxy对象!!!


比丘资源网 » Spring Security源码分析

发表回复

提供最优质的资源集合

立即查看 了解详情