一、认证流程总览
这里介绍目前主流微服务认证鉴权服务流程:
- 用户认证流程:用户向网关发送登录认证请求,网关将请求转发给认证服务。认证服务校验用户登录信息(用户密码、短信及图片验证码)等信息之后,如果校验成功颁发一个token令牌给该用户(这个令牌可以是JWT令牌)
- 网关级别访问鉴权:当用户访问系统内的其他业务服务接口时,需要携带登录认证的时候颁发的JWT token。网关验证JWT token的合法性,如果token不合法,则返回接口访问权限不足。如果token合法,则将请求按照网关的路由规则转发至相应的服务。
- 服务级别访问鉴权:网关级别的访问鉴权只是鉴别了JWT令牌的合法性,初步认定你是这个系统的用户,但是作为系统的用户并不意味着你可以访问所有的服务接口。通常基于用户的角色分类有更严格的访问权限划分。
二、认证服务流程细节
2.1 Spring Security认证总览
Spring Security认证核心过滤器链
基本的认证过程有三个步骤:
- Filter拦截请求,生成未认证Authentic,然后交由AuthenticationManager认证
- AuthenticationManager的默认实现Providermanager会通过AuthenticationProvider进行认证,其本身不做认证处理
- 如果认证通过,创建一个认证通过的Authentication返回,否则抛出异常
- Filter拦截请求,该Filter会将请求内容(比如用户名密码)封装为一个未认证的Authentication交给AuthenticationManager
- AuthenticationManager只负责管理AuthenticationProvider,不负责具体的认证工作,具体的认证工作交给Filter对应的xxProvider实现
- AuthenticationProvider实现类首先判断Authentication是否为自己负责,是则由自己处理,处理成功后创建一个认证通过的Authentication,处理失败抛出异常。如果不是自己处理则流转到下一个Provider处理
- UserDetailsService负责在AuthenticationProvider中查询用户信息并校验
如果我们需要新增个性化的认证类型,只要增加相应的Filter和与之对应的AuthenticationProvider即可
2.1 Spring Security基础组件
- Authentication接口:它的实现类表示当前访问系统的用户,封装用户相关信息
- AuthenticationManager接口:定义了认证Authentication的方法
- ProviderManager类:AuthenticationManager的默认实现类,仅负责xxProvider管理功能,具体认证功能由AuthenticationProvider实现类实现
- AuthenticationProvider接口:负责实际认证工作,有较多实现类
- UserDetailsService接口:提供loadUserByUserName方法我们可以重写该方法查询用户信息返回UserDetails
Authentication
public interface Authentication extends Principal, Serializable {
// 获取主体授权列表
Collection<? extends GrantedAuthority> getAuthorities();
// 获取主体凭证,比如密码
Object getCredentials();
// 获取主体携带的详细信息,比如ip
Object getDetails();
// 获取主体,通常为username
Object getPrincipal();
// 获取当前主体是否认证成功
boolean isAuthenticated();
// 设置当前主体是否认证成功状态
void setAuthenticated(boolean var1) throws IllegalArgumentException;
}
- 客户端请求到达过滤器链后,各过滤器会从请求中获取所需信息创建对应AuthenticationProvider的未认证Authentication
- AuthenticationProvider通过Authenticaition类型判断是否由自己处理
- Authentication认证成功后被保存到一个thread-local的SecurityContext中
AuthenticationManager
public interface AuthenticationManager {
Authentication authenticate(Authentication authentication)
throws AuthenticationException;
}
AuthenticationManager是一个接口,提供认证方法。认证通过后,返回的Authentication应该带上该principal所具有的GrantedAuthority
ProvideManager
ProvideManager是AuthenticationManager的默认实现,该类仅负责管理AuthenticationProvider功能,具体认证功能由各AuthenticationProvider执行
- 遍历所有AuthenticaitonProvider,找到支持的AuthenticationProvider进行认证
- AuthenticationProvider执行认证工作
- 认证通过不再进行下一个部门的认证,否则抛出异常被捕获,由下一个AuthenticationProvider认证
- 认证通过后执行后续逻辑,不通过抛出异常,否则表示没有配置对应AuthenticationProvider
AuthenticationProvider
public interface AuthenticationProvider {
// 进行认证
Authentication authenticate(Authentication authentication)
throws AuthenticationException;
// 是否由该AuthenticationProvider进行认证
boolean supports(Class<?> authentication);
}
AuthenticationProvider是一个接口定义了authenticate方法进行认证。我们可以实现该接口重写authenticate方法实现认证逻辑
UserDetailsService
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
UserDetailsService接口提供认证过程所需的UserDetails类。如果我们需要增加一个UserDetailsService,可以考虑实现UserDetailsService或者UserDetailsManager
2.2 新增一个认证流程
通过上述流程梳理,我们知道如果需要增加一个认证流程,只要增加一个Filter + AuthenticationProvider + UserDetailsService组合即可
参考: