@ -11,7 +11,7 @@
我们每次添加 `<artifactId>spring-boot-starter-security</artifactId>` ,启动的时候会有一条类似的日志:
我们每次添加 `<artifactId>spring-boot-starter-security</artifactId>` ,启动的时候会有一条类似的日志:
```
```txt
Using generated springSecurity password: 1db8eb87-e2ee-4c72-88e7-9b85268c4430
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
This generated password is for development use only. Your springSecurity configuration must be updated before running your
@ -20,9 +20,9 @@ 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 中。这些类就是 Spring Security 的全部了。
下面这些都是 springboot 自动装配类:
```imports
```java
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration
@ -284,7 +284,7 @@ public @interface EnableWebSecurity {
### WebSecurityConfiguration
### WebSecurityConfiguration
首先先看类注释(以后都默认翻译成简体中文.ali 翻译):
首先先看类注释 (以后都默认翻译成简体中文 .ali 翻译):
使用 WebSecurity 创建执行 Spring 安全 web 安全的 FilterChainProxy。然后导出必要的 bean。
使用 WebSecurity 创建执行 Spring 安全 web 安全的 FilterChainProxy。然后导出必要的 bean。
可以通过实现 WebSecurityConfigurer WebSecurityConfigurer 并将其公开为 Configuration 或公开 WebSecurityCustomizer bean 来进行自定义。
可以通过实现 WebSecurityConfigurer WebSecurityConfigurer 并将其公开为 Configuration 或公开 WebSecurityCustomizer bean 来进行自定义。
@ -476,7 +476,7 @@ protected final O doBuild() throws Exception {
剩下的都是一些创建一些 bean 了。
剩下的都是一些创建一些 bean 了。
`SecurityExpressionHandler` : 默认为`DefaultWebSecurityExpressionHandler`类(Facade 将 springSecurity 评估安全表达式的要求与基础表达式对象的实现隔离)
`SecurityExpressionHandler` : 默认为`DefaultWebSecurityExpressionHandler`类 (Facade 将 springSecurity 评估安全表达式的要求与基础表达式对象的实现隔离)
`WebInvocationPrivilegeEvaluator` : 为 `WebSecurity#performBuild()` 中创建的 `requestMatcherPrivilegeEvaluatorsEntries`
`WebInvocationPrivilegeEvaluator` : 为 `WebSecurity#performBuild()` 中创建的 `requestMatcherPrivilegeEvaluatorsEntries`
使用`RequestMatcherDelegatingWebInvocationPrivilegeEvaluator`包装。(允许用户确定他们是否具有给定 web URI 的特权。)
使用`RequestMatcherDelegatingWebInvocationPrivilegeEvaluator`包装。(允许用户确定他们是否具有给定 web URI 的特权。)
@ -506,7 +506,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
// 配置认证
// 配置认证
http.formLogin();
http.formLogin();
// 设置URL的授权问题
// 设置 URL 的授权问题
// 多个条件取交集
// 多个条件取交集
http.authorizeRequests()
http.authorizeRequests()
// 匹配 / 控制器 permitAll() 不需要被认证就可以访问
// 匹配 / 控制器 permitAll() 不需要被认证就可以访问
@ -516,7 +516,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
// anyRequest() 所有请求 authenticated() 必须被认证
// anyRequest() 所有请求 authenticated() 必须被认证
.anyRequest().authenticated();
.anyRequest().authenticated();
// .accessDecisionManager(accessDecisionManager());
// .accessDecisionManager(accessDecisionManager());
// 关闭csrf
// 关闭 csrf
http.csrf().disable();
http.csrf().disable();
return http.build();
return http.build();
}
}
@ -589,14 +589,14 @@ throw new IllegalArgumentException("The Filter class "+filter.getClass().getName
提示: 这个里面每次添加一个类,如果在`HttpSecurity`中调用`getOrApply`
提示: 这个里面每次添加一个类,如果在`HttpSecurity`中调用`getOrApply`
。比如这个代码调用的是`exceptionHandlingCustomizer.customize(getOrApply(new ExceptionHandlingConfigurer< >()));`。
。比如这个代码调用的是`exceptionHandlingCustomizer.customize(getOrApply(new ExceptionHandlingConfigurer< >()));`。
打开`ExceptionHandlingConfigurer`类,发现是一个`HttpSecurityBuilder`, 这样只需要看`configure`方法大概就能明白这个是一个什么类。
打开`ExceptionHandlingConfigurer`类,发现是一个`HttpSecurityBuilder`, 这样只需要看`configure`方法大概就能明白这个是一个什么类。
这个就是在 filter 中添加了一个`ExceptionTranslationFilter`filter.主要就是`SecurityConfigurer`
这个就是在 filter 中添加了一个`ExceptionTranslationFilter`filter. 主要就是`SecurityConfigurer`
的俩个方法。先调用`init(B builder)`,然后`configure(B builder)`
的俩个方法。先调用`init(B builder)`,然后`configure(B builder)`
后面都是一样,就跳过了
后面都是一样,就跳过了
> applyDefaultConfigurers(http);
> applyDefaultConfigurers(http);
这里的这一句,就是从"META-INF/spring.factories" 中加载并实例化给定类型的工厂实现
这里的这一句,就是从 "META-INF/spring.factories" 中加载并实例化给定类型的工厂实现
`SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader)`
`SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader)`
然后调用`http.apply(configurer);` 添加到`configurers`里面
然后调用`http.apply(configurer);` 添加到`configurers`里面
@ -637,7 +637,7 @@ throw new IllegalArgumentException("The Filter class "+filter.getClass().getName
进行构建, 这个就是非常重要的一个方法, build 对象,老规矩。进入`AbstractConfiguredSecurityBuilder#doBuild()`方法
进行构建, 这个就是非常重要的一个方法, build 对象,老规矩。进入`AbstractConfiguredSecurityBuilder#doBuild()`方法
`beforeInit();` : 还是没有什么
`beforeInit();` : 还是没有什么
`init()` : 调用里面所有的`configurers`里面的`init方法`,后面`HttpSecurity#doBuild`统一讲解,先把流程捋一遍
`init()` : 调用里面所有的`configurers`里面的`init 方法`,后面`HttpSecurity#doBuild`统一讲解,先把流程捋一遍
接下来`SecurityFilterChain`就已经创建好了,看一下里面的方法
接下来`SecurityFilterChain`就已经创建好了,看一下里面的方法
@ -689,22 +689,25 @@ public AuthenticationManagerBuilder authenticationManagerBuilder(ObjectPostProce
}
}
```
```
这里面返回了一个`AuthenticationManagerBuilder`的 bean, 也就是上面``
这里面返回了一个`AuthenticationManagerBuilder`的 bean, 也就是上面`HttpSecurityConfiguration#httpSecurity()`的时候需要的类,这个类也是一个`SecurityBuilder`。
HttpSecurityConfiguration#httpSecurity()`的时候需要的类,这个类也是一个`SecurityBuilder`。
> LazyPasswordEncoder defaultPasswordEncoder = new LazyPasswordEncoder(context);
```java
LazyPasswordEncoder defaultPasswordEncoder = new LazyPasswordEncoder(context);
```
首先创建了一个`LazyPasswordEncoder`,就是`PasswordEncoder`,用来管理密码的
首先创建了一个`LazyPasswordEncoder`,就是`PasswordEncoder`,用来管理密码的
> AuthenticationEventPublisher authenticationEventPublisher = getAuthenticationEventPublisher(context);
```java
AuthenticationEventPublisher authenticationEventPublisher = getAuthenticationEventPublisher(context);
```
这个就是在`SecurityAutoConfiguration`中创建的 springSecurity 的发布订阅,用来订阅事件
这个就是在 `SecurityAutoConfiguration` 中创建的 springSecurity 的发布订阅,用来订阅事件
```java
```java
DefaultPasswordEncoderAuthenticationManagerBuilder result = new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, defaultPasswordEncoder);
DefaultPasswordEncoderAuthenticationManagerBuilder result = new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, defaultPasswordEncoder);
```
```
就是 `AuthenticationManagerBuilder` 的真正实现了。接下来回到`getAuthenticationManager()`方法
就是 `AuthenticationManagerBuilder` 的真正实现了。接下来回到`getAuthenticationManager()`方法
```java
```java
public AuthenticationManager getAuthenticationManager() throws Exception {
public AuthenticationManager getAuthenticationManager() throws Exception {
@ -1128,7 +1131,7 @@ protected final void updateAuthenticationDefaults() {
2. `this.failureHandler` 设置为`new SimpleUrlAuthenticationFailureHandler(authenticationFailureUrl)`
2. `this.failureHandler` 设置为`new SimpleUrlAuthenticationFailureHandler(authenticationFailureUrl)`
里面的`authenticationFailureUrl`是`/login + "?error"`
里面的`authenticationFailureUrl`是`/login + "?error"`
`getBuilder().getConfigurer(LogoutConfigurer.class);` 就是前面加入的那一堆`Configurer`中的一个.这个默认就是当前设置的值,不用理会
`getBuilder().getConfigurer(LogoutConfigurer.class);` 就是前面加入的那一堆`Configurer`中的一个 . 这个默认就是当前设置的值,不用理会
> updateAccessDefaults(http);
> updateAccessDefaults(http);
@ -1144,8 +1147,8 @@ protected final void updateAuthenticationDefaults() {
```java
```java
/**
/**
* 开始一个身份验证方案。
* 开始一个身份验证方案。
在调用该方法之前, ExceptionTranslationFilter将使用请求的目标URL填充HttpSession属性abstractathenticationprocessingfilter.SPRING_SECURITY_SAVED_REQUEST _key。
在调用该方法之前, ExceptionTranslationFilter 将使用请求的目标 URL 填充 HttpSession 属性 abstractathenticationprocessingfilter.SPRING_SECURITY_SAVED_REQUEST _key。
实现应根据需要修改ServletResponse上的标头, 以开始身份验证过程。
实现应根据需要修改 ServletResponse 上的标头,以开始身份验证过程。
*/
*/
private LinkedHashMap< RequestMatcher , AuthenticationEntryPoint > defaultEntryPointMappings=new LinkedHashMap< >();
private LinkedHashMap< RequestMatcher , AuthenticationEntryPoint > defaultEntryPointMappings=new LinkedHashMap< >();