Servlet 认证架构
总体架构:
AuthenTicationFilter
AuthenticationFilter:用于获取请求中的信息,并创建 Authentication对象
AuthenticationProvider:用于验证登录逻辑,对Authentication进行进一步的身份认证
AuthenticationProvider
ProviderManager
您可以将多个AuthenticationProvider实例注入到ProviderManager。每个AuthenticationProvider执行特定类型的身份验证。
例如,DaoAuthenticationProvider支持基于用户名/密码的身份验证,同时JwtAuthenticationProvider支持对 JWT 令牌进行身份验证。
DaoAuthenticationProvider
输入Username和Password,返回UserDetails和Authorities
作用:是一个AuthenticationProvider,用于校验账号密码
SecurityContextHolder
Spring Security 身份验证模型的核心是SecurityContextHolder,它存在于TreadLocal中,
设置SecurityContextHolder
不能直接通过SecurityContextHolder.getContext().setAuthentication(authentication)来设置Holder中的context,否则多线程情况下会出现问题。应该为每个线程创建单独的实例:
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication authentication =
new TestingAuthenticationToken("username", "password", "ROLE_USER");
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
访问当前经过身份验证的用户
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
String username = authentication.getName();
Object principal = authentication.getPrincipal();
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
- 默认情况下,SecurityContextHolder使用
ThreadLocal来存储这些详细信息。 - ThreadLocal如果在处理当前主体的请求后注意清除线程,Spring Security 的
FilterChainProxy确保SecurityContext始终清除。 - 三者包含关系:SecurityContextHolder→ SecurityContext → Authentication
Authentication中包含:
-
principal:标识用户。当使用用户名/密码进行身份验证时,这通常是UserDetails. -
credentials: 通常是密码。很多情况下,这个是在用户通过认证后清除的,以保证不被泄露。authorities:GrantedAuthority实例是授予用户的高级权限。
UserDetails、UserDetailsService关系:
UserDetails由UserDetailsService返回。DaoAuthenticationProvider验证UserDetails,然后返回一个Authentication,该Authentication的主体是配置的UserDetailsService返回的UserDetails。