Spring Security 登录认证整体流程
以下是 Spring Security 登录认证流程的完整步骤,包括所有核心组件的参与和它们的作用:
1. 用户请求登录
- 用户通过浏览器发送 登录请求,通常为
POST /login
,并在请求体中携带用户名和密码。 - 请求会被 Spring Security 拦截器链中的过滤器捕获,默认处理登录的过滤器是
UsernamePasswordAuthenticationFilter
。
2. 进入 UsernamePasswordAuthenticationFilter
- 主要方法:
attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
- 从请求中提取用户提交的用户名和密码。
- 封装为一个未认证的
Authentication
对象(UsernamePasswordAuthenticationToken
)。 - 调用
AuthenticationManager
的authenticate(Authentication authentication)
方法,开始正式认证流程。
3. 进入 AuthenticationManager
AuthenticationManager
是认证的统一入口,负责协调认证的具体实现。- 默认实现:
ProviderManager
。 ProviderManager
会遍历其内部维护的多个AuthenticationProvider
,找到能处理当前认证的AuthenticationProvider
。
- 默认实现:
4. 进入 AuthenticationProvider
- 默认的
AuthenticationProvider
:DaoAuthenticationProvider
。- 核心方法:
authenticate(Authentication authentication)
- 验证逻辑:
- 校验
Authentication
的类型是否支持(这里是UsernamePasswordAuthenticationToken
)。 - 从
Authentication
对象中提取用户名。 - 调用
UserDetailsService
查询用户信息。
- 校验
- 核心方法:
5. 调用 UserDetailsService
查询用户信息
UserDetailsService
:- 根据用户名从数据库中加载用户信息。
- 返回一个
UserDetails
对象,包含用户的基本信息(用户名、加密密码、权限等)。
- 校验点:
- 如果用户不存在,抛出
UsernameNotFoundException
。 - 如果加载的用户信息为空,抛出
InternalAuthenticationServiceException
。
- 如果用户不存在,抛出
6. 校验密码
- 在
DaoAuthenticationProvider
中调用additionalAuthenticationChecks
方法:- 从
Authentication
中提取用户提交的明文密码。 - 从
UserDetails
中获取数据库中存储的加密密码。 - 使用
PasswordEncoder
比对明文密码和加密密码:- 明文密码加密后,和数据库中的加密密码进行比较。
- 如果比对失败,抛出
BadCredentialsException
。 - 如果比对成功,说明用户提交的密码正确。
- 从
7. 认证成功处理
- 如果认证成功:
- 调用
createSuccessAuthentication
方法创建一个新的 已认证的Authentication
对象。 - 包含:
- 用户信息(
principal
)。 - 权限信息(
GrantedAuthority
)。 - 其他附加信息(
details
)。
- 用户信息(
- 返回认证成功的
Authentication
对象。
- 调用
8. 认证成功后的处理
SecurityContextHolder
:- 将认证成功的
Authentication
对象存入全局的SecurityContextHolder
中。 - 这样后续的请求处理可以通过
SecurityContextHolder
获取当前用户的信息。
- 将认证成功的
- 跳转或返回响应:
- 如果认证成功,跳转到登录成功页面或返回成功响应。
- 如果认证失败,返回失败响应。
核心组件总结
1. 用户提交信息的载体
UsernamePasswordAuthenticationToken
:- 提交时:未认证(只有用户名和密码)。
- 认证成功后:已认证(包含用户信息、权限等)。
2. 认证管理器
AuthenticationManager
:- 负责统一调度认证逻辑。
- 默认实现是
ProviderManager
。
3. 认证提供者
AuthenticationProvider
:- 负责具体的认证逻辑。
- 默认实现是
DaoAuthenticationProvider
,结合UserDetailsService
和PasswordEncoder
实现用户名和密码校验。
4. 用户数据加载器
UserDetailsService
:- 用于从数据库或其他数据源中加载用户信息,返回
UserDetails
对象。
- 用于从数据库或其他数据源中加载用户信息,返回
5. 密码加密器
PasswordEncoder
:- 用于加密和校验用户密码。
6. 安全上下文
SecurityContextHolder
:- 存储认证成功的
Authentication
对象,作为后续请求的安全上下文。
- 存储认证成功的
登录流程简图
rust用户提交登录请求 ↓ UsernamePasswordAuthenticationFilter ↓ AuthenticationManager (ProviderManager) ↓ AuthenticationProvider (DaoAuthenticationProvider) ↓ UserDetailsService 加载用户信息 ↓ PasswordEncoder 校验密码 ↓ 认证成功 -> 保存到 SecurityContextHolder -> 返回成功响应 ↓ 认证失败 -> 返回失败响应
详细流程关键点
- 用户提交信息被封装为
UsernamePasswordAuthenticationToken
。 AuthenticationManager
调用具体的AuthenticationProvider
。UserDetailsService
加载用户信息。PasswordEncoder
比对密码。- 认证成功后,
Authentication
对象被存入SecurityContextHolder
。