spring security的密码认证逻辑

第一步:在我们自定义的LoginService里,使用@Resource注入一个AuthenticationManager

    @Resource
    private AuthenticationManager authenticationManager;

 

注入AuthenticationManager以后,就可以在LoginService的登录方法里,通过调用authenticationManager.authenticate方法,触发整个认证逻辑:

authentication = authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(username, password));

 

密码认证的起源是WebSecurityConfigurerAdapter.java在authenticate方法里,将认证过程委托给AuthenticationManager,由AuthenticationManager发起。

            if (this.delegate != null) {
                return this.delegate.authenticate(authentication);
            } else {
                synchronized(this.delegateMonitor) {
                    if (this.delegate == null) {
                        this.delegate = (AuthenticationManager)this.delegateBuilder.getObject();
                        this.delegateBuilder = null;
                    }
                }

                return this.delegate.authenticate(authentication);
            }

 

委托最终到了AbstractUserDetailsAuthenticationProvider.java,在authenticate方法里,会先从userCache里获取UserDetails,如果userCache里拿到的是null,就进行retrieveUser,也就是根据账号、密码到数据库里去取用户信息,以下仅为摘要,详细内容可参考org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.java

一、从userCache取

UserDetails user = this.userCache.getUserFromCache(username);

 

二、userCache拿到null,就retrieveUser,从数据库取

                user = retrieveUser(username,
                        (UsernamePasswordAuthenticationToken) authentication);

 

三、retrieveUser取的过程,如果发生异常,会抛出异常,如果顺利取到了用户信息,会进行preAuthenticationChecks和additionalAuthenticationChecks,preAuthenticationChecks通俗的理解就是:预检查,预检查的内容包括:账号是否被锁定,是否有效等等

user = retrieveUser(username,
(UsernamePasswordAuthenticationToken) authentication);
preAuthenticationChecks.check(user);
additionalAuthenticationChecks(user,
(UsernamePasswordAuthenticationToken) authentication);

 

四、preAuthenticationChecks通过以后,会进行postAuthenticationChecks,接着把用户信息写入到缓存,最后createSuccessAuthentication(principalToReturn, authentication, user)

postAuthenticationChecks.check(user);

if (!cacheWasUsed) {
this.userCache.putUserInCache(user);
}

Object principalToReturn = user;

if (forcePrincipalAsString) {
principalToReturn = user.getUsername();
}

return createSuccessAuthentication(principalToReturn, authentication, user);

 authenticate结束,会返回一个result的数据结构给到我们,表明认证的结果,如下图

 

如果这个result不为null,就会执行copyDetails,具体的代码逻辑如下:

                if (result != null) {
                    copyDetails(authentication, result);
                    break;
                }

 

copyDetails执行完,在最后阶段,会把result数据结构里对应的credentials重置为null,这样做的目的想必都可以理解,credentials就是明文密码,清空credentials是为了安全考量,至此认证过程就告一段落了。

posted @ 2022-04-26 13:43  jamstack  阅读(744)  评论(0编辑  收藏  举报