diff --git a/docs/SpringSecurity/SpringSecurity流程补充.md b/docs/SpringSecurity/SpringSecurity流程补充.md
index 849b943..d43bafa 100644
--- a/docs/SpringSecurity/SpringSecurity流程补充.md
+++ b/docs/SpringSecurity/SpringSecurity流程补充.md
@@ -1,27 +1,26 @@
-# springSecurity 流程补充
+# SpringSecurity 流程补充
注意:
1. 基于 spring-boot-dependencies:2.7.7
-2. 首先需要了解[springboot2.7 升级](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes)
- `Changes to Auto-configuration` 以后使用`autoconfigure`进行自动注入
-3.
-
-代码地址[io.github.poo0054](https://github.com/poo0054/security-study/blob/master/starter/src/main/java/io/github/poo0054/security/StarterApplication.java)
+2. 首先需要了解 [springboot2.7 升级](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes)
+ `Changes to Auto-configuration` 以后使用 `autoconfigure` 进行自动注入
+3. 代码地址 [io.github.poo0054](https://github.com/poo0054/security-study/blob/master/starter/src/main/java/io/github/poo0054/security/StarterApplication.java)
## 启动
-我们每次添加` spring-boot-starter-security`
-,启动的时候启动日志会有一条类似
-`Using generated springSecurity password: 1db8eb87-e2ee-4c72-88e7-9b85268c4430
+我们每次添加 `spring-boot-starter-security`,启动的时候会有一条类似的日志:
+
+```
+Using generated springSecurity password: 1db8eb87-e2ee-4c72-88e7-9b85268c4430
This generated password is for development use only. Your springSecurity configuration must be updated before running your
-application in production.`
+application in production.
+```
-的日志。找到`UserDetailsServiceAutoConfiguration#InMemoryUserDetailsManager`类,它是 springboot 自动装配的。
+找到 `UserDetailsServiceAutoConfiguration#InMemoryUserDetailsManager` 类,它是 springboot 自动装配的。
-下面这些都是 springboot 自动装配类,在`spring-boot-autoconfigure-2.7.7.jar`>META-INF>spring>
-org.springframework.boot.autoconfigure.AutoConfiguration.imports 中. 这些类就是 springSecurity 的全部了.
+下面这些都是 springboot 自动装配类,在 `spring-boot-autoconfigure-2.7.7.jar` > META-INF > spring > org.springframework.boot.autoconfigure.AutoConfiguration.imports 中。这些类就是 Spring Security 的全部了。
```imports
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
@@ -70,8 +69,6 @@ public class SecurityAutoConfiguration {
这个是 springSecurity 的核心配置类`SecurityProperties`,里面能配置
`filter`: 过滤,`user` : 用户信息
-`这个有个问题,filter是属于tomcat的,springSecurity 中使用什么方式让filter变的有序的`
-
### @Import({ SpringBootWebSecurityConfiguration.class, SecurityDataConfiguration.class })
这里导入了 2 个类 `SpringBootWebSecurityConfiguration`和`SecurityDataConfiguration`,`SecurityDataConfiguration`是 Spring
@@ -79,7 +76,7 @@ springSecurity 与 Spring 数据的集成,暂时不做讲解,重点是`Sprin
#### SpringBootWebSecurityConfiguration
-这个类就是一个`Configuration`类,条件必须为`@ConditionalOnWebApplication(type = Type.SERVLET)`才会注入
+这个类就是一个 `Configuration` 类,条件必须为 `@ConditionalOnWebApplication(type = Type.SERVLET)` 才会注入
##### SecurityFilterChainConfiguration
@@ -193,6 +190,7 @@ UserDetailsManager 的非持久化实现,支持内存映射。
## SecurityFilterAutoConfiguration
SpringSecurity 的过滤器
+
自动配置。与 SpringBootWebSecurityConfiguration 分开配置,以确保在存在用户提供的 WebSecurityConfiguration 时,过滤器的顺序仍然被配置。
### DelegatingFilterProxyRegistrationBean
@@ -329,28 +327,28 @@ public @interface EnableWebSecurity {
然后在`SecurityBuilder`的实现类`AbstractConfiguredSecurityBuilder`的`doBuild()`方法进行很多别的操作。
```java
-protected final O doBuild()throws Exception{
-synchronized (this.configurers){
- this.buildState=BuildState.INITIALIZING;
+protected final O doBuild() throws Exception {
+ synchronized (this.configurers) {
+ this.buildState = BuildState.INITIALIZING;
beforeInit();
init();
- this.buildState=BuildState.CONFIGURING;
+ this.buildState = BuildState.CONFIGURING;
beforeConfigure();
configure();
- this.buildState=BuildState.BUILDING;
- O result=performBuild();
- this.buildState=BuildState.BUILT;
+ this.buildState = BuildState.BUILDING;
+ O result = performBuild();
+ this.buildState = BuildState.BUILT;
return result;
- }
- }
+ }
+}
```
回到原来地方,返回的`webSecurityConfigurers`,里面的
```java
-for(SecurityConfigurer webSecurityConfigurer:webSecurityConfigurers){
- this.webSecurity.apply(webSecurityConfigurer);
- }
+for (SecurityConfigurer webSecurityConfigurer : webSecurityConfigurers) {
+ this.webSecurity.apply(webSecurityConfigurer);
+}
```
然后就到了`AbstractConfiguredSecurityBuilder#apply`方法,里面调用了`add(configurer);` 也就是把`SecurityConfigurer`
@@ -372,19 +370,19 @@ for(SecurityConfigurer webSecurityConfigurer:webSecurityCon
这个里面最关键的也就是这个了。
```java
- for(SecurityFilterChain securityFilterChain:this.securityFilterChains){
- this.webSecurity.addSecurityFilterChainBuilder(()->securityFilterChain);
- for(Filter filter:securityFilterChain.getFilters()){
- if(filter instanceof FilterSecurityInterceptor){
- this.webSecurity.securityInterceptor((FilterSecurityInterceptor)filter);
- break;
+for (SecurityFilterChain securityFilterChain : this.securityFilterChains) {
+ this.webSecurity.addSecurityFilterChainBuilder(() -> securityFilterChain);
+ for (Filter filter : securityFilterChain.getFilters()) {
+ if (filter instanceof FilterSecurityInterceptor) {
+ this.webSecurity.securityInterceptor((FilterSecurityInterceptor) filter);
+ break;
}
- }
- }
- for(WebSecurityCustomizer customizer:this.webSecurityCustomizers){
- customizer.customize(this.webSecurity);
- }
- return this.webSecurity.build();
+ }
+}
+for (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {
+ customizer.customize(this.webSecurity);
+}
+return this.webSecurity.build();
```
首先使用根据获取到的`securityFilterChains`set 入`WebSecurity#securityFilterChainBuilders`的 List 属性
@@ -419,10 +417,10 @@ static class SecurityFilterChainConfiguration {
继续回到上面,
```java
-if(filter instanceof FilterSecurityInterceptor){
- this.webSecurity.securityInterceptor((FilterSecurityInterceptor)filter);
- break;
- }
+if (filter instanceof FilterSecurityInterceptor) {
+ this.webSecurity.securityInterceptor((FilterSecurityInterceptor) filter);
+ break;
+}
```
`FilterSecurityInterceptor`也在这里进行处理,也就是`SecurityMetadataSource`元数据
@@ -430,28 +428,28 @@ if(filter instanceof FilterSecurityInterceptor){
然后自定义的`WebSecurityCustomizer`也在这里。可以自行改变`webSecurity`
```java
-for(WebSecurityCustomizer customizer:this.webSecurityCustomizers){
- customizer.customize(this.webSecurity);
- }
+for (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {
+ customizer.customize(this.webSecurity);
+}
```
-接下来就是构建了,来到`AbstractConfiguredSecurityBuilder#doBuild()`
+接下来就是构建了,来到 `AbstractConfiguredSecurityBuilder#doBuild()`
```java
-protected final O doBuild()throws Exception{
-synchronized (this.configurers){
- this.buildState=BuildState.INITIALIZING;
+protected final O doBuild() throws Exception {
+ synchronized (this.configurers) {
+ this.buildState = BuildState.INITIALIZING;
beforeInit();
init();
- this.buildState=BuildState.CONFIGURING;
+ this.buildState = BuildState.CONFIGURING;
beforeConfigure();
configure();
- this.buildState=BuildState.BUILDING;
- O result=performBuild();
- this.buildState=BuildState.BUILT;
+ this.buildState = BuildState.BUILDING;
+ O result = performBuild();
+ this.buildState = BuildState.BUILT;
return result;
- }
- }
+ }
+}
```
> init();
@@ -502,25 +500,25 @@ synchronized (this.configurers){
其实到了这一步。后面的就是我们自己编写的代码了比如
```java
- @Bean
-public SecurityFilterChain securityFilterChain(HttpSecurity http)throws Exception{
- // 配置认证
- http.formLogin();
-
- // 设置URL的授权问题
- // 多个条件取交集
- http.authorizeRequests()
- // 匹配 / 控制器 permitAll() 不需要被认证就可以访问
- .antMatchers("/login").permitAll()
- .antMatchers("/error").permitAll()
- .antMatchers("/fail").permitAll()
- // anyRequest() 所有请求 authenticated() 必须被认证
- .anyRequest().authenticated();
-// .accessDecisionManager(accessDecisionManager());
- // 关闭csrf
- http.csrf().disable();
- return http.build();
- }
+@Bean
+public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ // 配置认证
+ http.formLogin();
+
+ // 设置URL的授权问题
+ // 多个条件取交集
+ http.authorizeRequests()
+ // 匹配 / 控制器 permitAll() 不需要被认证就可以访问
+ .antMatchers("/login").permitAll()
+ .antMatchers("/error").permitAll()
+ .antMatchers("/fail").permitAll()
+ // anyRequest() 所有请求 authenticated() 必须被认证
+ .anyRequest().authenticated();
+ // .accessDecisionManager(accessDecisionManager());
+ // 关闭csrf
+ http.csrf().disable();
+ return http.build();
+}
```
或者继承 WebSecurityConfigurerAdapter 的类了。
@@ -530,12 +528,12 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http)throws Exceptio
```java
@Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER)
- SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http)throws Exception{
- http.authorizeRequests().anyRequest().authenticated();
- http.formLogin();
- http.httpBasic();
- return http.build();
- }
+SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
+ http.authorizeRequests().anyRequest().authenticated();
+ http.formLogin();
+ http.httpBasic();
+ return http.build();
+}
```
首先获取`HttpSecurity http`(这里的`HttpSecurity`是从`HttpSecurityConfiguration`
@@ -558,27 +556,27 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http)throws Exceptio
这个有一个很有意思的类`FilterOrderRegistration`。 前面问的根据 filter 是如何包装顺序的。就在这个类里面
```java
-FilterOrderRegistration(){
- Step order=new Step(INITIAL_ORDER,ORDER_STEP);
- put(DisableEncodeUrlFilter.class,order.next());
- put(ForceEagerSessionCreationFilter.class,order.next());
- put(ChannelProcessingFilter.class,order.next());
- order.next(); // gh-8105
- put(WebAsyncManagerIntegrationFilter.class,order.next());
- put(SecurityContextHolderFilter.class,order.next());
- put(SecurityContextPersistenceFilter.class,order.next());
- put(HeaderWriterFilter.class,order.next());
- put(CorsFilter.class,order.next());
- put(CsrfFilter.class,order.next());
- put(LogoutFilter.class,order.next());
-// .....
+FilterOrderRegistration() {
+ Step order = new Step(INITIAL_ORDER, ORDER_STEP);
+ put(DisableEncodeUrlFilter.class, order.next());
+ put(ForceEagerSessionCreationFilter.class, order.next());
+ put(ChannelProcessingFilter.class, order.next());
+ order.next(); // gh-8105
+ put(WebAsyncManagerIntegrationFilter.class, order.next());
+ put(SecurityContextHolderFilter.class, order.next());
+ put(SecurityContextPersistenceFilter.class, order.next());
+ put(HeaderWriterFilter.class, order.next());
+ put(CorsFilter.class, order.next());
+ put(CsrfFilter.class, order.next());
+ put(LogoutFilter.class, order.next());
+}
```
springSecurity 事先使用这个类把预加载的类全部排序好,然后每次 add 一个新的 filter 就会使用这个里面的序号。如果我们有自定义的类,也要提前加载到里面去,不然就会
```java
- throw new IllegalArgumentException("The Filter class "+filter.getClass().getName()
- +" does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.");
+throw new IllegalArgumentException("The Filter class "+filter.getClass().getName()
+ +" does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.");
```
`WebAsyncManagerIntegrationFilter`: 与处理异步 web 请求相关的实用程序方法
@@ -678,16 +676,16 @@ public interface SecurityFilterChain {
```java
@Bean
public AuthenticationManagerBuilder authenticationManagerBuilder(ObjectPostProcessor