diff --git a/docs/SpringSecurity/SpringSecurity流程补充.md b/docs/SpringSecurity/SpringSecurity流程补充.md
index 4744f7b..849b943 100644
--- a/docs/SpringSecurity/SpringSecurity流程补充.md
+++ b/docs/SpringSecurity/SpringSecurity流程补充.md
@@ -1,24 +1,27 @@
-# 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)
+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)
+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 security password: 1db8eb87-e2ee-4c72-88e7-9b85268c4430
+,启动的时候启动日志会有一条类似
+`Using generated springSecurity password: 1db8eb87-e2ee-4c72-88e7-9b85268c4430
-This generated password is for development use only. Your security configuration must be updated before running your
+This generated password is for development use only. Your springSecurity configuration must be updated before running your
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中. 这些类就是security的全部了.
+下面这些都是 springboot 自动装配类,在`spring-boot-autoconfigure-2.7.7.jar`>META-INF>spring>
+org.springframework.boot.autoconfigure.AutoConfiguration.imports 中. 这些类就是 springSecurity 的全部了.
```imports
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
@@ -64,27 +67,27 @@ public class SecurityAutoConfiguration {
### @EnableConfigurationProperties(SecurityProperties.class)
-这个是security的核心配置类`SecurityProperties`,里面能配置
-`filter`: 过滤,`user` : 用户信息
+这个是 springSecurity 的核心配置类`SecurityProperties`,里面能配置
+`filter`: 过滤,`user` : 用户信息
-`这个有个问题,filter是属于tomcat的,security中使用什么方式让filter变的有序的`
+`这个有个问题,filter是属于tomcat的,springSecurity 中使用什么方式让filter变的有序的`
### @Import({ SpringBootWebSecurityConfiguration.class, SecurityDataConfiguration.class })
-这里导入了2个类 `SpringBootWebSecurityConfiguration`和`SecurityDataConfiguration`,`SecurityDataConfiguration`是Spring
-Security与Spring数据的集成,暂时不做讲解,重点是`SpringBootWebSecurityConfiguration`
+这里导入了 2 个类 `SpringBootWebSecurityConfiguration`和`SecurityDataConfiguration`,`SecurityDataConfiguration`是 Spring
+springSecurity 与 Spring 数据的集成,暂时不做讲解,重点是`SpringBootWebSecurityConfiguration`
#### SpringBootWebSecurityConfiguration
-这个类就是一个`Configuration`类,条件必须为`@ConditionalOnWebApplication(type = Type.SERVLET)`才会注入
+这个类就是一个`Configuration`类,条件必须为`@ConditionalOnWebApplication(type = Type.SERVLET)`才会注入
##### SecurityFilterChainConfiguration
-其中第一个子类`SecurityFilterChainConfiguration`添加了`@ConditionalOnDefaultWebSecurity`,这个类有个注解
-`@Conditional(DefaultWebSecurityCondition.class)`,而`DefaultWebSecurityCondition`类继承了`AllNestedConditions`
+其中第一个子类`SecurityFilterChainConfiguration`添加了`@ConditionalOnDefaultWebSecurity`,这个类有个注解
+`@Conditional(DefaultWebSecurityCondition.class)`,而`DefaultWebSecurityCondition`类继承了`AllNestedConditions`
-所以下面代码就是判断该类是否生效,如果不存在`SecurityFilterChain`和`WebSecurityConfigurerAdapter`
-的bean,就生效.创建默认的`SecurityFilterChain`
+所以下面代码就是判断该类是否生效,如果不存在`SecurityFilterChain`和`WebSecurityConfigurerAdapter`
+的 bean,就生效。创建默认的`SecurityFilterChain`
```java
/**
@@ -115,42 +118,42 @@ class DefaultWebSecurityCondition extends AllNestedConditions {
}
```
-`SecurityFilterChain`就是整个springsecurity的流程了,有俩个方法,一个是`boolean matches(HttpServletRequest request);`
-,是否匹配这次请求,匹配成功就获取当前所有`Filter`进行处理
+`SecurityFilterChain`就是整个 springsecurity 的流程了,有俩个方法,一个是`boolean matches(HttpServletRequest request);`
+,是否匹配这次请求,匹配成功就获取当前所有`Filter`进行处理
`SecurityFilterChain`类会放在最下面单独讲解
##### ErrorPageSecurityFilterConfiguration
-这是第二个子类,主要就是通过`FilterRegistrationBean`注入了一个`ErrorPageSecurityFilter`. 用于拦截错误调度,以确保对错误页面的授权访问。
+这是第二个子类,主要就是通过`FilterRegistrationBean`注入了一个`ErrorPageSecurityFilter`。 用于拦截错误调度,以确保对错误页面的授权访问。
- ```java
- /**
- * Configures the {@link ErrorPageSecurityFilter}.
- */
+```java
+ /**
+* Configures the {@link ErrorPageSecurityFilter}
+*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(WebInvocationPrivilegeEvaluator.class)
@ConditionalOnBean(WebInvocationPrivilegeEvaluator.class)
static class ErrorPageSecurityFilterConfiguration {
- @Bean
- FilterRegistrationBean errorPageSecurityFilter(ApplicationContext context) {
- FilterRegistrationBean registration = new FilterRegistrationBean<>(
- new ErrorPageSecurityFilter(context));
- registration.setDispatcherTypes(DispatcherType.ERROR);
- return registration;
- }
+ @Bean
+ FilterRegistrationBean errorPageSecurityFilter(ApplicationContext context) {
+ FilterRegistrationBean registration = new FilterRegistrationBean<>(
+ new ErrorPageSecurityFilter(context));
+ registration.setDispatcherTypes(DispatcherType.ERROR);
+ return registration;
+ }
}
- ```
+```
##### WebSecurityEnablerConfiguration
-这个类主要就是添加了`@EnableWebSecurity`注解,这个注解也很重要,后面跟`SecurityFilterChain`一起讲解
+这个类主要就是添加了`@EnableWebSecurity`注解,这个注解也很重要,后面跟`SecurityFilterChain`一起讲解
### DefaultAuthenticationEventPublisher
-在类中还存在`SecurityAutoConfiguration`bean,这个是属于spring的发布订阅.改装一下,就是security的成功和失败事件,可以订阅失败后的一些处理,如日志打印等
+在类中还存在`SecurityAutoConfiguration`bean,这个是属于 spring 的发布订阅。改装一下,就是 springSecurity 的成功和失败事件,可以订阅失败后的一些处理,如日志打印等
```java
/**
@@ -180,40 +183,40 @@ public interface AuthenticationEventPublisher {
"org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector",
"org.springframework.security.oauth2.client.registration.ClientRegistrationRepository",
"org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository"})
- ```
+```
### InMemoryUserDetailsManager
-UserDetailsManager的非持久化实现,支持内存映射。
+UserDetailsManager 的非持久化实现,支持内存映射。
主要用于测试和演示目的,其中不需要完整的持久系统
## SecurityFilterAutoConfiguration
-Spring Security的过滤器
-自动配置。与SpringBootWebSecurityConfiguration分开配置,以确保在存在用户提供的WebSecurityConfiguration时,过滤器的顺序仍然被配置。
+SpringSecurity 的过滤器
+自动配置。与 SpringBootWebSecurityConfiguration 分开配置,以确保在存在用户提供的 WebSecurityConfiguration 时,过滤器的顺序仍然被配置。
### DelegatingFilterProxyRegistrationBean
-这个类是继承了`AbstractFilterRegistrationBean`,`FilterRegistrationBean`也是继承的`AbstractFilterRegistrationBean`
-.但是`DelegatingFilterProxyRegistrationBean`是使用的一个`targetBeanName`
-找到bean.进行注入.其中`private static final String DEFAULT_FILTER_NAME = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME;`
+这个类是继承了`AbstractFilterRegistrationBean`,`FilterRegistrationBean`也是继承的`AbstractFilterRegistrationBean`
+。但是`DelegatingFilterProxyRegistrationBean`是使用的一个`targetBeanName`
+找到 bean。进行注入。其中`private static final String DEFAULT_FILTER_NAME = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME;`
也就是`springSecurityFilterChain`
-其中有俩个属性, Order和DispatcherTypes
+其中有俩个属性, Order 和 DispatcherTypes
-* Order默认为-100
+- Order 默认为-100
-* `DispatcherType`就是`DispatcherType`类
+- `DispatcherType`就是`DispatcherType`类
`private Set dispatcherTypes = new HashSet<>(
- Arrays.asList(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.REQUEST));`
+Arrays.asList(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.REQUEST));`
-注意: 这里需要了解一下`DelegatingFilterProxyRegistrationBean`以及spring如何整合filter和mvc的.security核心就是filter
+注意: 这里需要了解一下`DelegatingFilterProxyRegistrationBean`以及 spring 如何整合 filter 和 mvc 的。 springSecurity 核心就是 filter
image.png
-`DelegatingFilterProxyRegistrationBean`和`FilterRegistrationBean`都是继承的`RegistrationBean`,而`RegistrationBean`
-又是`ServletContextInitializer`的实现类.其中`void onStartup(ServletContext servletContext)`方法是关键. 在`javax.servlet`
-中,存在这样一个类
+`DelegatingFilterProxyRegistrationBean`和`FilterRegistrationBean`都是继承的`RegistrationBean`,而`RegistrationBean`
+又是`ServletContextInitializer`的实现类。其中`void onStartup(ServletContext servletContext)`方法是关键。 在`javax.servlet`
+中,存在这样一个类
```java
public interface ServletContainerInitializer {
@@ -233,32 +236,32 @@ public interface ServletContainerInitializer {
void onStartup(Set> c, ServletContext ctx) throws ServletException;
```
-springboot中的`TomcatStarter`继承了这个类,而这个类又是spring启动的核心`AbstractApplicationContext#refresh()`
-中的`onRefresh();`方法.
+springboot 中的`TomcatStarter`继承了这个类,而这个类又是 spring 启动的核心`AbstractApplicationContext#refresh()`
+中的`onRefresh();`方法。
-找到实现类`ServletWebServerApplicationContext`的`onRefresh()`方法.里面有`createWebServer();`方法.
-在里面有创建`webServer`的方法.`this.webServer = factory.getWebServer(getSelfInitializer());`这个就是创建`tomcat`的工厂.
+找到实现类`ServletWebServerApplicationContext`的`onRefresh()`方法。里面有`createWebServer();`方法。
+在里面有创建`webServer`的方法。`this.webServer = factory.getWebServer(getSelfInitializer());`这个就是创建`tomcat`的工厂。
`TomcatServletWebServerFactory#getWebServer(ServletContextInitializer... initializers)`
-.里面就是创建tomcat,并启动`TomcatWebServer#initialize()`(这就是springboot不用tamcat的原因)
+。里面就是创建 tomcat,并启动`TomcatWebServer#initialize()`(这就是 springboot 不用 tamcat 的原因)
-而把filter注入servlet中的是`TomcatServletWebServerFactory#prepareContext(Host host, ServletContextInitializer[] initializers)`
+而把 filter 注入 servlet 中的是`TomcatServletWebServerFactory#prepareContext(Host host, ServletContextInitializer[] initializers)`
中的`TomcatServletWebServerFactory#configureContext(context, initializersToUse)`
-方法,在里面创建了一个`TomcatStarter starter = new TomcatStarter(initializers);`.而`TomcatStarter`
-继承了`ServletContainerInitializer`类.调用`ServletContainerInitializer#onStartup(ServletContext servletContext)`
-时候会进入到`RegistrationBean`中.
-然后`AbstractFilterRegistrationBean#addRegistration`里面添加filter
-`return servletContext.addFilter(getOrDeduceName(filter), filter);`这样每次请求servlet,tomcat就会先使用filter过滤器进行拦截
+方法,在里面创建了一个`TomcatStarter starter = new TomcatStarter(initializers);`。而`TomcatStarter`
+继承了`ServletContainerInitializer`类。调用`ServletContainerInitializer#onStartup(ServletContext servletContext)`
+时候会进入到`RegistrationBean`中。
+然后`AbstractFilterRegistrationBean#addRegistration`里面添加 filter
+`return servletContext.addFilter(getOrDeduceName(filter), filter);`这样每次请求 servlet,tomcat 就会先使用 filter 过滤器进行拦截
-简单来说就是`TomcatStarter`继承了`ServletContainerInitializer`.tomcat会调用`onStartup`
-方法,在这个方法里面会调用`ServletContextInitializer#onStartup`.在这个里面有`filter`和其余需要整合`ServletContext`的方法
+简单来说就是`TomcatStarter`继承了`ServletContainerInitializer`。tomcat 会调用`onStartup`
+方法,在这个方法里面会调用`ServletContextInitializer#onStartup`。在这个里面有`filter`和其余需要整合`ServletContext`的方法
-比如`springSecurityFilterChain`使用的是`DelegatingFilterProxyRegistrationBean`,需要使用bean去获取`getFilter`
-.而`ErrorPageFilter`使用的是`FilterRegistrationBean`.直接就可以注入
+比如`springSecurityFilterChain`使用的是`DelegatingFilterProxyRegistrationBean`,需要使用 bean 去获取`getFilter`
+。而`ErrorPageFilter`使用的是`FilterRegistrationBean`。直接就可以注入
## @EnableWebSecurity
-这个就是security的核心注解
-需要注意,`@EnableWebMvcSecurity`已经弃用,请使用`@EnableWebSecurity`
+这个就是 springSecurity 的核心注解
+需要注意,`@EnableWebMvcSecurity`已经弃用,请使用`@EnableWebSecurity`
```java
@@ -282,24 +285,25 @@ public @interface EnableWebSecurity {
### WebSecurityConfiguration
-首先先看类注释(以后都默认翻译成简体中文.ali翻译):
+首先先看类注释(以后都默认翻译成简体中文.ali 翻译):
-使用WebSecurity创建执行Spring安全web安全的FilterChainProxy。然后导出必要的bean。
-可以通过实现WebSecurityConfigurer WebSecurityConfigurer并将其公开为Configuration或公开WebSecurityCustomizer bean来进行自定义。
-使用EnableWebSecurity时会导入该配置。
+使用 WebSecurity 创建执行 Spring 安全 web 安全的 FilterChainProxy。然后导出必要的 bean。
+可以通过实现 WebSecurityConfigurer WebSecurityConfigurer 并将其公开为 Configuration 或公开 WebSecurityCustomizer bean 来进行自定义。
+使用 EnableWebSecurity 时会导入该配置。
#### setFilterChainProxySecurityConfigurer
逐行解释:
+
> this.webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
-`ObjectPostProcessor`也就是`AutowireBeanFactoryObjectPostProcessor`.在`AuthenticationConfiguration`
+`ObjectPostProcessor`也就是`AutowireBeanFactoryObjectPostProcessor`。在`AuthenticationConfiguration`
类上`@Import(ObjectPostProcessorConfiguration.class)`.
`AutowireBeanFactoryObjectPostProcessor`类里面创建`webSecurity`
`AutowireBeanFactoryObjectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));`
使用`AutowireCapableBeanFactory`创建出`WebSecurity`
-`AutowireBeanFactoryObjectPostProcessor`把`SmartInitializingSingleton`和`DisposableBean`拿出来,使用自己的`destroy()`
+`AutowireBeanFactoryObjectPostProcessor`把`SmartInitializingSingleton`和`DisposableBean`拿出来,使用自己的`destroy()`
和`afterSingletonsInstantiated()`执行
> List> webSecurityConfigurers = new
@@ -312,42 +316,46 @@ public @interface EnableWebSecurity {
先了解一下结构

-
-

-
-使用`WebSecurity`聚合了`private final LinkedHashMap>, List>> configurers = new LinkedHashMap<>();` 也就是`WebSecurityConfigurerAdapter`(当然还有别的,这里主要讲`WebSecurityConfigurerAdapter`)
+使用`WebSecurity`
+聚合了`private final LinkedHashMap>, List>> configurers = new LinkedHashMap<>();`
+也就是`WebSecurityConfigurerAdapter`(当然还有别的,这里主要讲`WebSecurityConfigurerAdapter`)
`WebSecurityConfigurerAdapter`也可以认为就是`SecurityConfigurer`
`WebSecurity`也就是`SecurityBuilder`
-然后在`SecurityBuilder`的实现类`AbstractConfiguredSecurityBuilder`的`doBuild()`方法进行很多别的操作.
+然后在`SecurityBuilder`的实现类`AbstractConfiguredSecurityBuilder`的`doBuild()`方法进行很多别的操作。
+
```java
-protected final O doBuild() throws Exception {
- synchronized (this.configurers) {
- this.buildState = BuildState.INITIALIZING;
- beforeInit();
- init();
- this.buildState = BuildState.CONFIGURING;
- beforeConfigure();
- configure();
- this.buildState = BuildState.BUILDING;
- O result = performBuild();
- this.buildState = BuildState.BUILT;
- return result;
- }
- }
+protected final O doBuild()throws Exception{
+synchronized (this.configurers){
+ this.buildState=BuildState.INITIALIZING;
+ beforeInit();
+ init();
+ this.buildState=BuildState.CONFIGURING;
+ beforeConfigure();
+ configure();
+ this.buildState=BuildState.BUILDING;
+ O result=performBuild();
+ this.buildState=BuildState.BUILT;
+ return result;
+ }
+ }
```
-回到原来地方,返回的`webSecurityConfigurers`,里面的
+回到原来地方,返回的`webSecurityConfigurers`,里面的
+
```java
-for (SecurityConfigurer webSecurityConfigurer : webSecurityConfigurers) {
- this.webSecurity.apply(webSecurityConfigurer);
- }
+for(SecurityConfigurer webSecurityConfigurer:webSecurityConfigurers){
+ this.webSecurity.apply(webSecurityConfigurer);
+ }
```
-然后就到了`AbstractConfiguredSecurityBuilder#apply`方法,里面调用了`add(configurer);` 也就是把`SecurityConfigurer`放入了`AbstractConfiguredSecurityBuilder#configurers`的一个map中,这样就使用`SecurityBuilder`聚合了`SecurityConfigurer`. 在构建的时候可以做一些事情
+
+然后就到了`AbstractConfiguredSecurityBuilder#apply`方法,里面调用了`add(configurer);` 也就是把`SecurityConfigurer`
+放入了`AbstractConfiguredSecurityBuilder#configurers`的一个 map 中,这样就使用`SecurityBuilder`聚合了`SecurityConfigurer`。
+在构建的时候可以做一些事情
也就是说使用`WebSecurity`聚合了`SecurityConfigurer`(包括`WebSecurityConfigurerAdapter`)
@@ -358,88 +366,98 @@ for (SecurityConfigurer webSecurityConfigurer : webSecurity
> this.webSecurityCustomizers = webSecurityCustomizers;
获取所有`webSecurityCustomizers`
-
-#### public Filter springSecurityFilterChain()
-这个里面最关键的也就是这个了.
+#### public Filter springSecurityFilterChain()
+
+这个里面最关键的也就是这个了。
+
```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 (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {
- customizer.customize(this.webSecurity);
- }
- return this.webSecurity.build();
+ 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();
```
-首先使用根据获取到的`securityFilterChains`set入`WebSecurity#securityFilterChainBuilders`的List属性
+首先使用根据获取到的`securityFilterChains`set 入`WebSecurity#securityFilterChainBuilders`的 List 属性
+
+这里有个需要注意的地方,如果你继承了`WebSecurityConfigurerAdapter`。`this.securityFilterChains` 就是一个空的。
-这里有个需要注意的地方,如果你继承了`WebSecurityConfigurerAdapter`.`this.securityFilterChains` 就是一个空的.
+而且会由`WebSecurityConfigurerAdapter#getHttp()`进行创建`WebSecurity`
+。这就跟 spring 的 order 有关了。 `@Order(SecurityProperties.BASIC_AUTH_ORDER)`
-而且会由`WebSecurityConfigurerAdapter#getHttp()`进行创建`WebSecurity`.这就跟spring的order有关了. `@Order(SecurityProperties.BASIC_AUTH_ORDER)`
+其中`SpringBootWebSecurityConfiguration#SecurityFilterChainConfiguration`有一个注解`@ConditionalOnDefaultWebSecurity`
-其中`SpringBootWebSecurityConfiguration#SecurityFilterChainConfiguration`有一个注解`@ConditionalOnDefaultWebSecurity`
```java
+
@Configuration(proxyBeanMethods = false)
- @ConditionalOnDefaultWebSecurity
- static class SecurityFilterChainConfiguration {
-
- @Bean
- @Order(SecurityProperties.BASIC_AUTH_ORDER)
- SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
- http.authorizeRequests().anyRequest().authenticated();
- http.formLogin();
- http.httpBasic();
- return http.build();
- }
-
- }
+@ConditionalOnDefaultWebSecurity
+static class SecurityFilterChainConfiguration {
+
+ @Bean
+ @Order(SecurityProperties.BASIC_AUTH_ORDER)
+ SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
+ http.authorizeRequests().anyRequest().authenticated();
+ http.formLogin();
+ http.httpBasic();
+ return http.build();
+ }
+
+}
```
-这里会创建`SecurityFilterChain`. 还会有一个`HttpSecurity`的注入
-继续回到上面,
+这里会创建`SecurityFilterChain`。 还会有一个`HttpSecurity`的注入
+
+继续回到上面,
+
```java
-if (filter instanceof FilterSecurityInterceptor) {
- this.webSecurity.securityInterceptor((FilterSecurityInterceptor) filter);
- break;
- }
+if(filter instanceof FilterSecurityInterceptor){
+ this.webSecurity.securityInterceptor((FilterSecurityInterceptor)filter);
+ break;
+ }
```
-`FilterSecurityInterceptor`也在这里进行处理,也就是`SecurityMetadataSource`元数据
-然后自定义的`WebSecurityCustomizer`也在这里.可以自行改变`webSecurity`
-```java
-for (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {
- customizer.customize(this.webSecurity);
- }
+`FilterSecurityInterceptor`也在这里进行处理,也就是`SecurityMetadataSource`元数据
+
+然后自定义的`WebSecurityCustomizer`也在这里。可以自行改变`webSecurity`
+
+```java
+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;
- beforeInit();
- init();
- this.buildState = BuildState.CONFIGURING;
- beforeConfigure();
- configure();
- this.buildState = BuildState.BUILDING;
- O result = performBuild();
- this.buildState = BuildState.BUILT;
- return result;
- }
- }
+protected final O doBuild()throws Exception{
+synchronized (this.configurers){
+ this.buildState=BuildState.INITIALIZING;
+ beforeInit();
+ init();
+ this.buildState=BuildState.CONFIGURING;
+ beforeConfigure();
+ configure();
+ this.buildState=BuildState.BUILDING;
+ O result=performBuild();
+ this.buildState=BuildState.BUILT;
+ return result;
+ }
+ }
```
+
> init();
-如果继承了`WebSecurityConfigurerAdapter`,就会在这里创建`HttpSecurity`
+> 如果继承了`WebSecurityConfigurerAdapter`,就会在这里创建`HttpSecurity`
-注意: 这里个`buildState`,用来控制当前状态的
+注意: 这里个`buildState`,用来控制当前状态的
> beforeConfigure();
@@ -451,130 +469,148 @@ protected final O doBuild() throws Exception {
> O result = performBuild();
-然后就到了`WebSecurity#performBuild()`.
+然后就到了`WebSecurity#performBuild()`。
1. 首先排除忽略的`RequestMatcher`
2. 添加入`securityFilterChain` 和`requestMatcherPrivilegeEvaluatorsEntries`
-3. 创建出`FilterChainProxy`bean的名称为`springSecurityFilterChain` (重点)
+3. 创建出`FilterChainProxy`bean 的名称为`springSecurityFilterChain` (重点)
-剩下的都是一些创建一些bean了.
+剩下的都是一些创建一些 bean 了。
-`SecurityExpressionHandler`: 默认为`DefaultWebSecurityExpressionHandler`类(Facade将Spring Security评估安全表达式的要求与基础表达式对象的实现隔离)
-
-`WebInvocationPrivilegeEvaluator`: 为 `WebSecurity#performBuild()`中创建的 `requestMatcherPrivilegeEvaluatorsEntries` 使用`RequestMatcherDelegatingWebInvocationPrivilegeEvaluator`包装.(允许用户确定他们是否具有给定web URI的特权。)
+`SecurityExpressionHandler`: 默认为`DefaultWebSecurityExpressionHandler`类(Facade 将 springSecurity 评估安全表达式的要求与基础表达式对象的实现隔离)
-这俩个类都是很重要的. 一个是解析器,一个是判断uri是否合格的类. 后面单独讲
+`WebInvocationPrivilegeEvaluator`: 为 `WebSecurity#performBuild()`中创建的 `requestMatcherPrivilegeEvaluatorsEntries`
+使用`RequestMatcherDelegatingWebInvocationPrivilegeEvaluator`包装。(允许用户确定他们是否具有给定 web URI 的特权。)
+这俩个类都是很重要的。 一个是解析器,一个是判断 uri 是否合格的类。 后面单独讲
### HttpSecurityConfiguration
-接下来到了`HttpSecurityConfiguration`
-根据上面`WebSecurityConfiguration`,可以得出.`WebSecurityConfiguration`创建`WebSecurity`,`WebSecurity`创建了`FilterChainProxy`的bean.
+接下来到了`HttpSecurityConfiguration`
+
+根据上面`WebSecurityConfiguration`,可以得出。`WebSecurityConfiguration`创建`WebSecurity`,`WebSecurity`
+创建了`FilterChainProxy`的 bean。
-`HttpSecurityConfiguration`创建`HttpSecurity`. 而在`SecurityFilterChainConfiguration`类中,使用`HttpSecurity`创建了`SecurityFilterChain`.这也就是我们使用了`WebSecurityConfigurerAdapter`.为什么会存在`SecurityFilterChain`类的原因.是`SecurityFilterChainConfiguration#defaultSecurityFilterChain`创建了一个`SecurityFilterChain`.
+`HttpSecurityConfiguration`创建`HttpSecurity`。 而在`SecurityFilterChainConfiguration`类中,使用`HttpSecurity`
+创建了`SecurityFilterChain`。这也就是我们使用了`WebSecurityConfigurerAdapter`。为什么会存在`SecurityFilterChain`
+类的原因。是`SecurityFilterChainConfiguration#defaultSecurityFilterChain`创建了一个`SecurityFilterChain`。
-得出结论,`FilterChainProxy`持有`SecurityFilterChain`.而`DelegatingFilterProxyRegistrationBean`又持有`FilterChainProxy`
+得出结论,`FilterChainProxy`持有`SecurityFilterChain`。而`DelegatingFilterProxyRegistrationBean`又持有`FilterChainProxy`
`DelegatingFilterProxyRegistrationBean`->`FilterChainProxy`->`SecurityFilterChain`
+其实到了这一步。后面的就是我们自己编写的代码了比如
-其实到了这一步.后面的就是我们自己编写的代码了比如
```java
@Bean
- public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+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();
+ // 匹配 / 控制器 permitAll() 不需要被认证就可以访问
+ .antMatchers("/login").permitAll()
+ .antMatchers("/error").permitAll()
+ .antMatchers("/fail").permitAll()
+ // anyRequest() 所有请求 authenticated() 必须被认证
+ .anyRequest().authenticated();
// .accessDecisionManager(accessDecisionManager());
// 关闭csrf
http.csrf().disable();
return http.build();
- }
+ }
```
-或者继承WebSecurityConfigurerAdapter的类了.
+或者继承 WebSecurityConfigurerAdapter 的类了。
+
+这里我们用 springSecurity 默认的`SpringBootWebSecurityConfiguration`来举例
-这里我们用security默认的`SpringBootWebSecurityConfiguration`来举例
```java
@Bean
- @Order(SecurityProperties.BASIC_AUTH_ORDER)
- SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
- http.authorizeRequests().anyRequest().authenticated();
- http.formLogin();
- http.httpBasic();
- return http.build();
- }
+@Order(SecurityProperties.BASIC_AUTH_ORDER)
+ SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http)throws Exception{
+ http.authorizeRequests().anyRequest().authenticated();
+ http.formLogin();
+ http.httpBasic();
+ return http.build();
+ }
```
-首先获取`HttpSecurity http`(这里的`HttpSecurity`是从`HttpSecurityConfiguration`里面创建的,如果是自定义的`SecurityFilterChain`就是从自己写的里面来的)
+首先获取`HttpSecurity http`(这里的`HttpSecurity`是从`HttpSecurityConfiguration`
+里面创建的,如果是自定义的`SecurityFilterChain`就是从自己写的里面来的)
> 我们来到`HttpSecurityConfiguration#httpSecurity()`
-先创建一个默认的密码管理器,
+> 先创建一个默认的密码管理器,
-接下来进入`authenticationBuilder.parentAuthenticationManager(authenticationManager());`,这里就是`AuthenticationConfiguration`里面的处理.这个类后面和springaop加载我们写的注释单独在`@EnableGlobalAuthentication`注解类说
+接下来进入`authenticationBuilder.parentAuthenticationManager(authenticationManager());`
+,这里就是`AuthenticationConfiguration`
+里面的处理。这个类后面和 springaop 加载我们写的注释单独在`@EnableGlobalAuthentication`注解类说
-接着创建` HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());`,
+接着创建` HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());`,
> .csrf(withDefaults())
-启用CSRF保护,创建`CsrfConfigurer`类,并添加入添加入`AbstractConfiguredSecurityBuilder#configurers`.
+> 启用 CSRF 保护,创建`CsrfConfigurer`类,并添加入添加入`AbstractConfiguredSecurityBuilder#configurers`
> .addFilter(new WebAsyncManagerIntegrationFilter())
-这个有一个很有意思的类`FilterOrderRegistration`. 前面问的根据filter是如何包装顺序的.就在这个类里面
+这个有一个很有意思的类`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());
+// .....
```
-security事先使用这个类把预加载的类全部排序好,然后每次add一个新的filter就会使用这个里面的序号.如果我们有自定义的类,也要提前加载到里面去,不然就会
+
+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请求相关的实用程序方法
+`WebAsyncManagerIntegrationFilter`: 与处理异步 web 请求相关的实用程序方法
> .exceptionHandling(withDefaults())
这个是异常的处理
-提示: 这个里面每次添加一个类,如果在`HttpSecurity`中调用`getOrApply`.比如这个代码调用的是`exceptionHandlingCustomizer.customize(getOrApply(new ExceptionHandlingConfigurer<>()));`. 打开`ExceptionHandlingConfigurer`类,发现是一个`HttpSecurityBuilder`, 这样只需要看`configure`方法大概就能明白这个是一个什么类. 这个就是在filter中添加了一个`ExceptionTranslationFilter`filter.主要就是`SecurityConfigurer`的俩个方法.先调用`init(B builder)`,然后`configure(B builder)`
+提示: 这个里面每次添加一个类,如果在`HttpSecurity`中调用`getOrApply`
+。比如这个代码调用的是`exceptionHandlingCustomizer.customize(getOrApply(new ExceptionHandlingConfigurer<>()));`。
+打开`ExceptionHandlingConfigurer`类,发现是一个`HttpSecurityBuilder`, 这样只需要看`configure`方法大概就能明白这个是一个什么类。
+这个就是在 filter 中添加了一个`ExceptionTranslationFilter`filter.主要就是`SecurityConfigurer`
+的俩个方法。先调用`init(B builder)`,然后`configure(B builder)`
+
+后面都是一样,就跳过了
-后面都是一样,就跳过了
-
> applyDefaultConfigurers(http);
-这里的这一句,就是从"META-INF/spring.factories" 中加载并实例化给定类型的工厂实现
+这里的这一句,就是从"META-INF/spring.factories" 中加载并实例化给定类型的工厂实现
`SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader)`
然后调用`http.apply(configurer);` 添加到`configurers`里面
接下来回到`SecurityFilterChainConfiguration`类
->http.authorizeRequests().anyRequest().authenticated();
-首先添加了`http.authorizeRequests()` 然后调用 `return getOrApply(new ExpressionUrlAuthorizationConfigurer<>(context)).getRegistry();`.
-先把`ExpressionUrlAuthorizationConfigurer`放入config中,返回一个调用了`getRegistry()`. 也就是`ExpressionInterceptUrlRegistry`类.
+> http.authorizeRequests().anyRequest().authenticated();
-后面调用的`.anyRequest()`,也就是`AbstractRequestMatcherRegistry#anyRequest()`.先了解一下结构图
+首先添加了`http.authorizeRequests()`
+然后调用 `return getOrApply(new ExpressionUrlAuthorizationConfigurer<>(context)).getRegistry();`。
+先把`ExpressionUrlAuthorizationConfigurer`放入 config 中,返回一个调用了`getRegistry()`。
+也就是`ExpressionInterceptUrlRegistry`类。
+
+后面调用的`.anyRequest()`,也就是`AbstractRequestMatcherRegistry#anyRequest()`。先了解一下结构图

@@ -582,13 +618,16 @@ security事先使用这个类把预加载的类全部排序好,然后每次add
`http.authorizeRequests().anyRequest().authenticated();`是需要所有请求登录后才能访问
-1. `authorizeRequests`是创建了一个`ExpressionUrlAuthorizationConfigurer`并添加入configurer中.
-2. `anyRequest`是创建了一个`new AuthorizedUrl(requestMatchers)`,其中 `requestMatchers`是`AnyRequestMatcher.INSTANCE;`也就是`AnyRequestMatcher`对象.里面`matches(HttpServletRequest request)`直接返回ture
-3. `authenticated()`也就是授权,`ExpressionInterceptUrlRegistry#addMapping`.里面放入了一个`UrlMapping`,`UrlMapping`的俩个属性,一个是`AnyRequestMatcher`(所有请求),`configAttrs`表示`SecurityConfig`.`SecurityConfig`的值为`private static final String authenticated = "authenticated"`
+1. `authorizeRequests`是创建了一个`ExpressionUrlAuthorizationConfigurer`并添加入 configurer 中。
+2. `anyRequest`是创建了一个`new AuthorizedUrl(requestMatchers)`,其中 `requestMatchers`
+ 是`AnyRequestMatcher.INSTANCE;`也就是`AnyRequestMatcher`对象。里面`matches(HttpServletRequest request)`直接返回 ture
+3. `authenticated()`也就是授权,`ExpressionInterceptUrlRegistry#addMapping`。里面放入了一个`UrlMapping`,`UrlMapping`
+ 的俩个属性,一个是`AnyRequestMatcher`(所有请求),`configAttrs`表示`SecurityConfig`。`SecurityConfig`
+ 的值为`private static final String authenticated = "authenticated"`
> http.formLogin();
-创建了一个`FormLoginConfigurer`,也就是`SecurityConfigurer`.关注`init`和`configure`方法.后面统一讲解
+创建了一个`FormLoginConfigurer`,也就是`SecurityConfigurer`。关注`init`和`configure`方法。后面统一讲解
> http.httpBasic();
@@ -596,12 +635,13 @@ security事先使用这个类把预加载的类全部排序好,然后每次add
> http.build()
-进行构建,这个就是非常重要的一个方法,build对象,老规矩.进入`AbstractConfiguredSecurityBuilder#doBuild()`方法
+进行构建,这个就是非常重要的一个方法,build 对象,老规矩。进入`AbstractConfiguredSecurityBuilder#doBuild()`方法
`beforeInit();`: 还是没有什么
-`init()`: 调用里面所有的`configurers`里面的`init方法`,后面`HttpSecurity#doBuild`统一讲解,先把流程捋一遍
+`init()`: 调用里面所有的`configurers`里面的`init方法`,后面`HttpSecurity#doBuild`统一讲解,先把流程捋一遍
+
+接下来`SecurityFilterChain`就已经创建好了,看一下里面的方法
-接下来`SecurityFilterChain`就已经创建好了,看一下里面的方法
```java
/**
* Defines a filter chain which is capable of being matched against an
@@ -614,102 +654,114 @@ security事先使用这个类把预加载的类全部排序好,然后每次add
*/
public interface SecurityFilterChain {
- boolean matches(HttpServletRequest request);
+ boolean matches(HttpServletRequest request);
- List getFilters();
+ List getFilters();
}
```
-肯定是先匹配,如果成功了,就返回里面所有的filter进行过滤,比如刚刚设置的所有请求需要登录,也还有我们需要排除的请求
-`SecurityAutoConfiguration`类就已经大致讲完了,
+肯定是先匹配,如果成功了,就返回里面所有的 filter 进行过滤,比如刚刚设置的所有请求需要登录,也还有我们需要排除的请求
+
+`SecurityAutoConfiguration`类就已经大致讲完了,
### @EnableGlobalAuthentication
+
当前注解在`@EnableSecurity`中会自动加上
#### @Import(AuthenticationConfiguration.class)
-`AuthenticationConfiguration`上面`@Import(ObjectPostProcessorConfiguration.class)`. 以前使用的`ObjectPostProcessor`就是在这里注入的,注入`AutowireBeanFactoryObjectPostProcessor`对象
+`AuthenticationConfiguration`上面`@Import(ObjectPostProcessorConfiguration.class)`。 以前使用的`ObjectPostProcessor`
+就是在这里注入的,注入`AutowireBeanFactoryObjectPostProcessor`对象
#### AuthenticationManagerBuilder
-```java
+
+```java
@Bean
- public AuthenticationManagerBuilder authenticationManagerBuilder(ObjectPostProcessor