SpringSecurity------ Username/Password Authentication(九)
用户名和密码的获取方式
最常见的用户身份认证就是使用用户名密码,Spring Security为使用用户名和密码进行身份验证提供了全面的支持。 Spring Security提供了以下内置机制来从HttpServletRequest读取用户名和密码
1、表单登录(Form Login)
(1)在未经过认证的情况下向/private发送了一个请求
(2)FilterSecurityInterceptor通过抛出AccessDeniedException异常通知应用程序拒绝未经身份验证的请求
(3)由于检测到用户没有经过身份认证,ExceptionTranslationFilter会启动身份验证机制,并且通过LoginUrlAuthenticationEntryPoint通知客户端
(4)客户端会向服务端通过/login请求登录
(5)服务端向客户端提供登录页面数据
当用户提交了用户名和密码之后,UsernamePasswordAuthenticationFilter会对用户名和密码进行验证
(1)当用户提交用户名和密码后,UsernamePasswordAuthenticationFilter会从HttpServletRequest中获取到用户提交的用户名和密码信息,然后使用这些信息创建一个UsernamePasswordAuthenticationToken(Authentication类型)。
(2)UsernamePasswordAuthenticationToken会被传递到AuthenticationManager中进行身份验证。
(3)如果鉴权失败
- 清除SecurityContextHolder
- 执行RememberMeServices.loginFail,如果没有配置remember-me,则不执行
- AuthenticationFailureHandler执行
(4)如果认证成功
- 通知SessionAuthenticationStrategy有一个新的登录用户
- 将Authentication设置到SecurityContextHolder
- 执行RememberMeServices.loginSuccess,如果没有配置remember-me,则不执行
- ApplicationEventPublisher发布InteractiveAuthenticationSuccessEvent事件
- AuthenticationSuccessHandler执行。通常这里是一个SimpleUrlAuthenticationSuccessHandler 的实例,可以在登录成功后将用户引导到先前访问的页面
2、基础认证(Basic Authentication)
(1)在未经过认证的情况下向/private发送了一个请求
(2)FilterSecurityInterceptor通过抛出AccessDeniedException异常通知应用程序拒绝未经身份验证的请求
(3)ExceptionTranslationFilter会启动身份验证机制,并且通过BasicAuthenticationEntryPoint添加WWW-Authenticate响应头通知客户端
当客户端收到WWW-Authenticate报头时,会提示用户进行登录
(1)当用户提交用户名和密码后,UsernamePasswordAuthenticationFilter会从HttpServletRequest中获取到用户提交的用户名和密码信息,然后使用这些信息创建一个UsernamePasswordAuthenticationToken(Authentication类型)。
(2)UsernamePasswordAuthenticationToken会被传递到AuthenticationManager中进行身份验证。
(3)如果鉴权失败
- 清除SecurityContextHolder
- 执行RememberMeServices.loginFail,如果没有配置remember-me,则不执行
- AuthenticationEntryPoint 会继续发送WWW-Authenticate到客户端
(4)如果认证成功
- 将Authentication设置到SecurityContextHolder
- 执行RememberMeServices.loginSuccess,如果没有配置remember-me,则不执行
- BasicAuthenticationFilter通过FilterChain.doFilter(request,response)执行应用程序的后续任务
3、摘要认证(Digest Authentication)
简单介绍以下使用配置,这个不建议使用
@Autowired
UserDetailsService userDetailsService;
DigestAuthenticationEntryPoint entryPoint() {
DigestAuthenticationEntryPoint result = new DigestAuthenticationEntryPoint();
result.setRealmName("My App Relam");
result.setKey("3028472b-da34-4501-bfd8-a355c42bdf92");
}
DigestAuthenticationFilter digestAuthenticationFilter() {
DigestAuthenticationFilter result = new DigestAuthenticationFilter();
result.setUserDetailsService(userDetailsService);
result.setAuthenticationEntryPoint(entryPoint());
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.exceptionHandling(e -> e.authenticationEntryPoint(authenticationEntryPoint()))
.addFilterBefore(digestFilter());
return http.build();
}