From 2bf8e0206287160a2db6e9abd1528b6c5fa09b5d Mon Sep 17 00:00:00 2001 From: Rikako Wu <496063163@qq.com> Date: Sat, 8 Oct 2022 23:26:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=97=A5=E5=B8=B8=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spring/Spring Security/Spring Security.md | 62 ++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/spring/Spring Security/Spring Security.md b/spring/Spring Security/Spring Security.md index 206cc39..93884c2 100644 --- a/spring/Spring Security/Spring Security.md +++ b/spring/Spring Security/Spring Security.md @@ -99,4 +99,64 @@ ProviderManager是AuthenticationManager的最通用实现。ProviderManager将 > 在实践中,每个AuthenticationProvider知道如何处理一种特定类型的Authentication -默认情况下,ProviderManager在认证请求成功后会尝试清除返回的Authentication对象中任何敏感的凭据信息,这将会保证password等敏感信息保存时间尽可能地短,减少泄露的风险。 \ No newline at end of file +默认情况下,ProviderManager在认证请求成功后会尝试清除返回的Authentication对象中任何敏感的凭据信息,这将会保证password等敏感信息保存时间尽可能地短,减少泄露的风险。 + +### AuthenticationProvider +复数个AuthenticationProvider可以被注入到ProviderManager中,每个AuthenticationProvider可以负责一种专门类型的认证,例如DaoAuthenticationProvider负责username/password认证,JwtAuthenticationProvider负责jwt token的认证。 + +### AuthenticationEntryPoint +AuthenticationEntryPoint用来发送一个Http Response,用来向客户端请求认证凭据。 +某些情况下,客户端在请求资源时会主动在请求中包含凭据,如username/password等。在这种情况下,服务端并不需要再专门发送Http Response来向客户端请求认证凭据。 +> AuthenticationEntryPoint用来向客户端请求认证凭据,AuthenticationEntryPoint的实现可能会执行一个从定向操作,将请求重定向到一个登录页面用于获取凭据,并且返回一个WWW-Authentication Header。 + +### AbstractAuthenticationProcessingFilter +该类作为base filter用来对用户的凭据进行认证。再凭据被认证之前,Spring Security通常会通过AuthenticationEntryPoint向客户端请求认证凭据。 +之后,AbstractAuthenticationProcessingFilter会对提交的任何认证请求进行认证。 +#### 认证流程 +1. 当用户提交认证凭据之后,AbstractAuthenticationProcesingFilter会根据HttpServletRequest对象创建一个Authentication对象用于认证,该Authentication的类型取决于AbstractAuthenticationProcessingFilter的子类类型。例如,UsernamePasswordAuthenticationFilter会通过提交request中的username和password创建UsernamePasswordAuthenticationToken。 +2. 然后将构建产生的Authentication对象传入到AuthenticationManager中,进行认证 +3. 如果认证失败,那么会失败,SecurityContextHolder会被清空,RememberMeService.logFail方法将会被调用,AuthenticationFailureHandler也会被调用 +4. 如果认证成功,那么SessionAuthenticationStrategy将会收到登录的通知 +5. 该Authentication对象再认证成功之后将会被设置到SecurityContextHolder中 +6. RemeberMeService.logSuccess将会被调用 +7. ApplicationEventPublisher发布InteractiveAuthenticationSuccessEvent. +8. AuthenticationSuccessHandler被调用 + +## 用户名/密码认证 +### Form Login +Spring Security为以表单形式提供的用户名和密码认证提供支持。 +#### 用户被重定向到登录页面的过程 +1. 用户发送了一个没有经过身份认证的请求到指定资源,并且待请求的资源对该用户来说是未授权的 +2. Spring Security中FilterSecurityInterceptor抛出AccessDeniedException,代表该未授权的请求被拒绝 +3. 因为该用户没有经过认证,故而ExceptionTransactionFilter发起了开始认证的过程,并且使用配置好的AuthenticationEntryPoint向登录页面发起了重定向。在大多数情况下AuthenticationEntryPoint都是LoginUrlAuthenticationEntryPoint +4. 浏览器接下来会请求重定向到的登陆页面 + +当用户名和密码提交后,UsernamePasswordAuthenticationFilter会对username和password进行认证。UsernamePasswordAuthenticationFilter继承了AbstractAuthenticationProcessingFilter。 + +#### 认证用户名和密码过程 +1. 当用户提交了其用户名和密码之后,UsernamePasswordAuthenticationFilter会创建一个UsernamePasswordAuthenticationToken +2. 创建的UsernamePasswordAuthenticationToken会传入AuthenticationManager中进行认证 +3. 如果认证失败,那么SecurityContextHolder会被清除,RememberMeService.logFailure和AuthenticationFailureHandler会被调用 +4. 如果认证成功,那么SessionAuthenticationStrategy将会收到登录的通知,RemeberMeService.logSuccess和AuthenticationSuccessHandler会被调用,ApplicationEventPublisher发布InteractiveAuthenticationSuccessEvent + +Spring Security Form Login默认情况下是开启的,但是,一旦任何基于servlet的配置被提供,那么基于表单的login也必须要显式指定。 +```java +// 显式指定form login的配置 +@Bean +public SecurityFilterChain filterChain(HttpSecurity http) { + http + .formLogin(withDefaults()); + // ... +} +``` +如果想要自定义login form page,可以使用如下配置 +```java +public SecurityFilterChain filterChain(HttpSecurity http) { + http + .formLogin(form -> form + .loginPage("/login") + .permitAll() + ); + // ... +} +```