您现在的位置是:首页 >其他 >Springboot中SpringSecurity自动装配原理,源码级别绝对详细网站首页其他

Springboot中SpringSecurity自动装配原理,源码级别绝对详细

笔深 2023-11-07 00:00:04
简介Springboot中SpringSecurity自动装配原理,源码级别绝对详细

Springboot中SpringSecurity自动装配原理

(1)Springboot有一个自动配置类SecurityFilterAutoConfigurationSecurityFilterAutoConfiguration只要当项目中引入了SpringSecurity的相关jar包就会被自动加载。装载这个类是干嘛的呢?
(2)如下图,SecurityFilterAutoConfiguration 自动配置类主要用于,当存在名字叫做"springSecurityFilterChain"的bean时,就会往容器中注入一个DelegatingFilterProxyRegistrationBean类对象。所以SecurityFilterAutoConfiguration类对象主要用于生成DelegatingFilterProxyRegistrationBean类对象。
那么名字叫做"springSecurityFilterChain"的bean是从哪里来的呢?我们先按下不表,我们先看下这个DelegatingFilterProxyRegistrationBean类对象是干嘛的。
1684311377493.png
(3)通过下图的继承关系,我们可以看到DelegatingFilterProxyRegistrationBean类继承了RegistrationBean类,而RegistrationBean类实现了ServletContextInitializer接口。
(ServletContextInitializer是springboot内置tomcat时,tomcat初始化后会在TomcatStarter的onStartup方法中调用所有实现了ServletContextInitializer接口的onStartup方法。
和这个类似的是WebApplicationInitializer,WebApplicationInitializer是外置tomcat时,tomcat初始化后会调用程序的SpringServletContainerInitializer类的onStartup,而在onStartup方法中会调用所有实现了WebApplicationInitializer接口的onStartup方法
其实就是tomcat初始化后要调用一个类,然后在这个类中调用程序中某个接口所有实现类的onStartup方法进行处理。

1684396479207.png
1684396520408.png
也就是当servlet容器创建成功后,会自动执行DelegatingFilterProxyRegistrationBean类的onStartup方法。那么它是做了什么操作呢?
(4)通过调式可以追踪到核心的方法链,onStartup()->register()->addRegistration()->getFilter(),最终getFilter()获得的过滤器注册到了servlet容器中。需要注意的是上面一系列方法有些是DelegatingFilterProxyRegistrationBean从父类继承过来的,有些是自己重写的。
1684399887148.jpg
1684399911939.png
1684399937205.png
1684400022409.png
也就是说DelegatingFilterProxyRegistrationBean类的作用是注册了一个过滤器。这个过滤器其实是DelegatingFilterProxy的匿名类。
(5)既然DelegatingFilterProxy是过滤器,那么肯定要看它在doFilter()方法做了什么。
1684400187240.png
1684400246423.png
通过上面的源码,我们可以知道,doFilter()中主要是获取了一个过滤器对象delegateToUse,然后调用了delegateToUse的doFilter()方法。下面我们看看initDelegate()方法获得的是一个怎么样的过滤器对象。
1684400511070.png
可以看到initDelegate()方法中,从spring容器中获取了一个名叫this.getTargetBeanName()的过滤器对象,而this.getTargetBeanName()其实就是我们一开始的"springSecurityFilterChain"。
那么DelegatingFilterProxy类的作用其实就是执行到它时,暂停原有的过滤器链,先执行名叫"springSecurityFilterChain"过滤器的doFilter()方法。

总结上面几步:
SecurityFilterAutoConfiguration自动装配为了注入DelegatingFilterProxyRegistrationBean类DelegatingFilterProxyRegistrationBean类为了向servlet容器注册DelegatingFilterProxy过滤器,DelegatingFilterProxy过滤器中执行名叫"springSecurityFilterChain"的过滤器。
需要注意的是以上的其实都是在springboot中的类,而名叫"springSecurityFilterChain"的过滤器其实是在SpringSecurity中。也就是说上面绕了一大圈,其实目的就是为了实现你引入SpringSecurity的依赖,springboot将SpringSecurity中的过滤器加入到项目中来,而你却什么都不用配置。

(6)名叫"springSecurityFilterChain"的过滤器对象到底是哪里来的?
通过断点可以看到SpringSecurity包中有一个WebSecurityConfiguration类中注入了名叫"springSecurityFilterChain"的FilterChainProxy类对象。我们对FilterChainProxy干嘛的先按下不表,WebSecurityConfiguration又是什么时候注入的呢?要知道WebSecurityConfiguration是在SpringSecurity包中的,我们在项目中又没有主动创建过。
1684401615166.png
1684401673774.png
(7)在SpringSecurity的配置包下有一个 @EnableWebSecurity,在该注解上通过@Import引入了上面的WebSecurityConfiguration类,也就是说我想在我项目中使用SpringSecurity,应该需要在项目中添加@EnableWebSecurity,但是为什么我没加也能使用?
1684376978262.png
(8)大家回头看下(1)中自动装配的SecurityFilterAutoConfiguration,它的类上有一个@AutoConfigureAfter(SecurityAutoConfiguration.class)注解,也就是springboot在这之前会装置一个SecurityAutoConfiguration类。
1684401946214.png
SecurityAutoConfiguration类上,通过@Import引入了四个类,而 @EnableWebSecurity就在其中的SpringBootWebSecurityConfiguration或WebSecurityEnablerConfiguration头上(根据版本有关)

以上总结:->表示右边类通过左边类引入到程序中
第一条线为了创建SpringSecurity的过滤器链(对应上面的6-8步):自动装配了SecurityAutoConfiguration类->@EnableWebSecurity注解->WebSecurityConfiguration类->FilterChainProxy对象(名叫“springSecurityFilterChain”
第二条线为了将SpringSecurity过滤器链插入到servlet过滤器链中(对应上面的1-5布):对应之前的总结。

也就是现在,引入了SpringSecurity后,当有请求到来时,就会触发FilterChainProxy的doFilter()。
(9)FilterChainProxy虽然自己是过滤器,但是通过名字也不难看出,它同时是过滤器链的代理,也就是在该类中保存了SpringSecurity一系列的过滤器链。
1684402788064.png
如下图源码,FilterChainProxy的doFilter()中调用了doFilterInternal()方法,
1684402491729.png
而doFilterInternal()获取了本次请求路径相关的过滤器,然后组合成一个过滤器链,最后调用这个过滤器链。
1684402551901.png
也就是说FilterChainProxy的作用是根据请求路径选择过滤器,将选择的过滤器组合成一个过滤器链。然后执行这条过滤器链。

以上便是SpringSecurity的自动装配原理了。欢迎交流。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。