shiro登录流程源码分析
*关键点:跟踪token的去向
分析整个登录流程,以token去向为线索,层层追踪,直到跟我们自定义的realm验证方法结合。
1.获取Subject实例(实例通常是DelegatingSubject 或者是其子类)
Subject subject = SecurityUtils.getSubject();
2.调用登录
subject.login(token)(这里的token收集方式不重要)
可能是从页面传递上来的用户名和密码或者其他的方式收集的信息,通过:
UsernamePasswordToken token = new UsernamePasswordToken(userName(),password());
获取token,并调用subject.login(token)
这里的subject.login是DelegatingSubject实例的login,所以我们跟踪到DelegatingSubject的login
在该方法中,有源码如下
Subject subject = this.securityManager.login(this, token);
3.调用securityManager.login方法
SecurityManager是一个接口,我们追踪login的方法实现其实现类为:DefaultSecurityManager
方法中的源码如下
info = this.authenticate(token);
4.调用SecurityManager.authenticate方法
在SecurityManager实现类DefaultSecurityManager中将token转交给自身实现了Ahthenticator接口的authenticate方法
在此方法中,只有简单的一句代码
return this.authenticator.authenticate(token);
5.调用Authenticator.authenticate方法
在上一步的SecurityManager方法中调用了成员变量authenticator的authenticate方法。
SecurityManager是AuthenticatingSecurityManager的子类
在该类中实现了SecurityManager的authenticate方法,在实现方法中调用了:authenticator.authenticate(token)
成员authenticator是ModularRealmAuthenticator类的实例
这个地方非常关键:也就是在这里,SecurityManager把token转交到realm中进行验证。
这里调用了ModularRealmAuthenticator的方法authenticate
但是authenticate方法的实现是在ModularRealmAuthenticator的父类AbstractAuthenticator中实现的
所以我们现在把视角转到AbstractAuthenticator.authenticate方法中。
在AbstractAuthenticator.authenticate方法中,我们看到了token被传递给了自身的方法doAuthenticate
源码如下:
info = this.doAuthenticate(token);
6.调用ModularRealmAuthenticator.doAuthenticate方法
通过源码追踪,我们知道,只有ModularRealmAuthenticator类实现了doAuthenticate方法
到了这里,我们就可以看到一些比较熟悉的代码了:
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
this.assertRealmsConfigured();
Collection<Realm> realms = this.getRealms();
return realms.size() == 1 ? this.doSingleRealmAuthentication((Realm)realms.iterator