Spring Security认证

147 阅读4分钟

一、认证流程总览

这里介绍目前主流微服务认证鉴权服务流程:

image.png

  • 用户认证流程:用户向网关发送登录认证请求,网关将请求转发给认证服务。认证服务校验用户登录信息(用户密码、短信及图片验证码)等信息之后,如果校验成功颁发一个token令牌给该用户(这个令牌可以是JWT令牌)
  • 网关级别访问鉴权:当用户访问系统内的其他业务服务接口时,需要携带登录认证的时候颁发的JWT token。网关验证JWT token的合法性,如果token不合法,则返回接口访问权限不足。如果token合法,则将请求按照网关的路由规则转发至相应的服务。
  • 服务级别访问鉴权:网关级别的访问鉴权只是鉴别了JWT令牌的合法性,初步认定你是这个系统的用户,但是作为系统的用户并不意味着你可以访问所有的服务接口。通常基于用户的角色分类有更严格的访问权限划分。

二、认证服务流程细节

2.1 Spring Security认证总览

Spring Security认证核心过滤器链

image.png

基本的认证过程有三个步骤:

  • Filter拦截请求,生成未认证Authentic,然后交由AuthenticationManager认证
  • AuthenticationManager的默认实现Providermanager会通过AuthenticationProvider进行认证,其本身不做认证处理
  • 如果认证通过,创建一个认证通过的Authentication返回,否则抛出异常

image.png

  • 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组合即可

image.png

参考: