Spring Security登陆验证流程源码解析

1、登陆认证基于过滤器链

Spring Security的登陆验证流程核心就是过滤器链。当一个请求到达时按照过滤器链的顺序依次进行处理,经过全部过滤器链的验证,就能够访问API接口了。spring

file

SpringSecurity提供了多种登陆认证的方式,由多种Filter过滤器来实现,好比:数据库

  • BasicAuthenticationFilter实现的是HttpBasic模式的登陆认证
  • UsernamePasswordAuthenticationFilter实现用户名密码的登陆认证
  • RememberMeAuthenticationFilter实现登陆认证的“记住我”的功能
  • SmsCodeAuthenticationFilter实现短信验证码登陆认证
  • SocialAuthenticationFilter实现社交媒体方式登陆认证的处理
  • Oauth2AuthenticationProcessingFilter和Oauth2ClientAuthenticationProcessingFilter实现Oauth2的鉴权方式

根据咱们不一样的需求实现及配置,不一样的Filter会被加载到应用中。springboot

2、结合源码讲解登陆验证流程

咱们就以用户名、密码登陆方式为例讲解一下Spring Security的登陆认证流程。ide

file

2.1 UsernamePasswordAuthenticationFilter

该过滤器封装用户基本信息(用户名、密码),定义登陆表单数据接收相关的信息。如:学习

  • 默认的表单用户名密码input框name是username、password
  • 默认的处理登陆请求路径是/login、使用POST方法

file
file

2.2 AbstractAuthenticationProcessingFilter的doFilter方法的验证过程

UsernamePasswordAuthenticationFilter继承自抽象类AbstractAuthenticationProcessingFilter,该抽象类定义了验证成功与验证失败的处理方法。
file3d

2.3 验证成功以后的Handler和验证失败以后的handler

file

也就是说当咱们须要自定义验证成功或失败的处理方法时,要去实现AuthenticationSuccessHandler或AuthenticationfailureHandler接口code

file

3、登陆验证内部细节

3.1多种认证方式的管理 ProviderManager

ProviderManager用继承于AuthenticationManager是登陆验证的核心类。ProviderManager保管了多个AuthenticationProvider,用于不一样类型的登陆验证。好比:blog

  • RememberMeAuthenticationProvider定义了“记住我”功能的登陆验证逻辑
  • DaoAuthenticationProvider加载数据库用户信息,进行用户密码的登陆验证
public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean {
    ……
    private List<AuthenticationProvider> providers;
    ……

下文是ProviderManager的核心源码,遍历不一样登陆验证的AuthenticationProvider,只有当这种方式被支持的时候,才执行具体的登陆验证逻辑。
file继承

3.2 登陆认证接口 AuthenticationProvider

public interface AuthenticationProvider {
    Authentication authenticate(Authentication var1) throws AuthenticationException;

    boolean supports(Class<?> var1);
}

AuthenticationProvider的实现类定义了具体的登陆验证逻辑接口

file

3.3 数据库加载用户信息 DaoAuthenticationProvider

public class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

从数据库获取用户信息源码

file

因此当咱们须要加载用户信息进行登陆验证的时候,咱们须要实现UserDetailsService接口,重写loadUserByUsername方法,参数是用户输入的用户名。返回值是UserDetails

期待您的关注

相关文章
相关标签/搜索