(六)Spring Security 认证流程

本文详细介绍了Spring Security的认证流程,从用户提交用户名和密码开始,经过UsernamePasswordAuthenticationFilter,再到AuthenticationManager的认证过程,重点解析了Authentication、AuthenticationProvider、ProviderManager以及UserDetailsService和PasswordEncoder的角色和工作原理。通过自定义AuthenticationProvider和UserDetailsService,可以实现认证的按需定制,以适应各种不同的认证需求。
摘要由CSDN通过智能技术生成

认证流程

在这里插入图片描述
图片来自于:黑马程序员SpringSecurity认证课程

认证过程:

  1. 用户提交用户名、密码被SecurityFilterChain中的UsernamePasswordAuthenticationFilter 过滤器获取到,封装为请求Authentication,通常情况下是UsernamePasswordAuthenticationToken这个实现类。
  2. 然后过滤器将Authentication提交至认证管理器(AuthenticationManager)进行认证
  3. 认证成功后, AuthenticationManager身份管理器返回一个被填充满了信息的(包括上面提到的权限信息,身份信息,细节信息,但密码通常会被移除) Authentication 实例。
  4. SecurityContextHolder 安全上下文容器将第3步填充了信息的 Authentication ,通过SecurityContextHolder.getContext().setAuthentication(…)方法,设置到其中。可以看出AuthenticationManager接口(认证管理器)是认证相关的核心接口,也是发起认证的出发点,它
    的实现类为ProviderManager。而Spring Security支持多种认证方式,因此ProviderManager维护着一个
    List 列表,存放多种认证方式,最终实际的认证工作是由
    AuthenticationProvider完成的。咱们知道web表单的对应的AuthenticationProvider实现类为
    DaoAuthenticationProvider,它的内部又维护着一个UserDetailsService负责UserDetails的获取。最终
    AuthenticationProvider将UserDetails填充至Authentication。
    认证核心组件的大体关系如下:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Eg2sjTq4-1599134067449)(F7BB8422DBB94B699003912F92800ECA)]
    图片来自于:黑马程序员SpringSecurity认证课程

知识点认识

Authentication

我们所面对的系统中的用户,在Spring Security中被称为主体(principal)。主体包含了所有能够经过验证而获得系统访问权限的用户、设备或其他系统。主体的概念实际上来自 Java Security,Spring Security通过一层包装将其定义为一个Authentication。

public interface Authentication extends Principal, Serializable {
   
    // 获取主体授权列表
    Collection<? extends GrantedAuthority> getAuthorities();

    // 获取主体凭证,一般为密码
    Object getCredentials();
    
    // 获取主体携带的详细信息
    Object getDetails();
    
    // 获取主体,通常为username
    Object getPrincipal();

    // 获取当前主体是否认证成功
    boolean isAuthenticated();

    // 设置当前主体是否认证成功状态
    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

AuthenticateProvider

Spring Security 认证的过程其实就是一个构建Authentication的过程。Authentication 在Spring Security的各个AuthenticationProvider中流动,AuthenticationProvider被Spring Security定义为一个验证过程:

public interface AuthenticationProvider {
   
    // 验证完成,成功,返回一个验证完成的Authentication
    Authentication authenticate(Authentication var1) throws AuthenticationException;

    // 是否支持验证当前的Authentication类型
    boolean supports(Class<?> var1);
}

大部分场景下身份验证都是基于用户名和密码进行的,所以Spring Security提供了一个UsernamePasswordAuthenticationToken用于代指这一类证。,每一个登录用户即主体都被包装为一个UsernamePasswordAuthenticationToken,从而在Spring Security的各个AuthenticationProvider中流动。

ProviderManager

一次完整的认证可以包含多个AuthenticationProvider,一般由ProviderManager管理。

public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean {
   
    private static final Log logger = LogFactory.getLog(ProviderManager.class);
    private AuthenticationEventPublisher eventPublisher;
    
    // AuthenticationProvider 列表
    private List<AuthenticationProvider> providers;
    protected MessageSourceAccessor messages;
    private AuthenticationManager parent;
    private boolean eraseCredentialsAfterAuthentication;

    public ProviderManager(List<AuthenticationProvider> providers) {
   
        this(providers, (AuthenticationManager)null);
    }

    public ProviderManager(List<AuthenticationProvider> providers, AuthenticationManager parent) {
   
        this.eventPublisher = new ProviderManager.NullEventPublisher();
        this.providers = Collections.emptyList();
        this.messages = SpringSecurityMessageSource.getAccessor();
        this.eraseCredentialsAfterAuthentication = true;
        Assert.notNull(providers, "providers list cannot be null");
        this.providers = providers;
        this.parent = parent;
        this.checkState();
    }

    public void afterPropertiesSet() {
   
        this.checkState();
    }

    private void checkState() {
   
        if (this.parent == null && this.providers.isEmpty()) {
   
            throw new IllegalArgumentException("A parent AuthenticationManager or a list of AuthenticationProviders is required");
        }
    }

    // 迭代AuthenticationProvider 列表,进行认证,返回最终结果
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
   
        Class<? extends Authentication> toTest = authentication.getClass();
        AuthenticationException lastException = null;
        AuthenticationException parentException = null;
        Authentication result = null;
        Authentication parentResult = null;
        boolean debug = logger.isDebugEnabled();
        Iterator var8 = this.getProviders().iterator();

        // 迭代
        while(var8.hasNext()) {
   
            AuthenticationProvider provider = (AuthenticationProvider)var8.next();
            // 判断AuthenticationProvider 是否支持当前验证
            if (provider.supports(toTest)) {
   
                if (debug) {
   
                    logger.debug("Authentication attempt using " + provider.getClass().getName());
                }

                try {
   
                    // 执行AuthenticationProvider的认证。
                    result = provider.authenticate(authentication);
                    if (result != null) {
   
                        this.copyDetails(authentication, result);
                        // 有一个验证通过,就返回
                        break;
                    }
                } catch (InternalAuthenticationServiceException | AccountStatusException var13) {
   
                    this.prepareException
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Security是一个基于Spring框架的安全框架,它提供了一套完整的安全认证和授权机制。下面是Spring Security认证流程: 1. 用户访问需要认证的资源,Spring Security会拦截请求并重定向到登录页面。 2. 用户输入用户名和密码,提交表单。 3. Spring Security会将表单提交的用户名和密码封装成一个Authentication对象。 4. AuthenticationManager接口会根据Authentication对象中的用户名和密码去调用UserDetailsService接口的实现类获取用户信息。 5. 如果获取到用户信息,则将用户信息封装成一个包含权限信息的Authentication对象返回给AuthenticationManager。 6. AuthenticationManager会将Authentication对象交给AuthenticationProvider接口的实现类进行认证。 7. 如果认证成功,则将认证成功的Authentication对象返回给Spring Security。 8. Spring Security会将认证成功的Authentication对象存储到SecurityContextHolder中,供后续的访问授权使用。 下面是一个简单的Spring Security认证流程的代码示例: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .antMatchers("/user/**").hasAnyRole("ADMIN", "USER") .anyRequest().authenticated() .and() .formLogin() .and() .logout().logoutSuccessUrl("/login").permitAll(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值