Shiro认证源码解析和工作原理
来源:互联网 发布:淘宝e5620电脑才卖1000 编辑:程序博客网 时间:2024/06/09 21:10
先行回顾一下使用shiro的步骤:
1. 创建Subject实例对象currUser;
2. 判断当前currUser是否认证过;
3. 如果没有认证过,那么应当调用currUser的login(token)方法,token也就是令牌,用以封装用户输入的登录信息;
4. 实现自定义Realm,用以完成和数据库的交互,由Shiro底层来完成用户输入信息和数据库信息的比对,完成认证。
当然与此同时,还需要完成一些Spring IOC 中bean的配置。
currUser的login()方法
首先Subject是一个接口,当我们查看login方法的源码时,该方法的具体实现是DelegatingSubject来完成的。
在DelegatingSubject类中,我们可以看到以下代码
//这说明login操作事实上是由securityManager来完成的Subject subject = this.securityManager.login(this, token);
该securityManager已经在我们的Spring容器中配置,并且指定了它的cacheManager以及realm。再向下看,这个securityManager是DefaultSecurityManger的实例,DefaultSecurityManger继承了SessionsSecurityManager,由它来完成login操作。它的login方法
//它需要传入的参数是Subject实例以及一个tokenpublic Subject login(Subject subject, AuthenticationToken token) throws AuthenticationException { AuthenticationInfo info; try { //这里的info就是数据库提取数据的封装 info = this.authenticate(token); } catch (AuthenticationException var7) { AuthenticationException ae = var7; try { this.onFailedLogin(token, ae, subject); } catch (Exception var6) { if (log.isInfoEnabled()) { log.info("onFailedLogin method threw an exception. Logging and propagating original AuthenticationException.", var6); } } throw var7; } Subject loggedIn = this.createSubject(token, info, subject); this.onSuccessfulLogin(token, info, loggedIn); return loggedIn; }
上述方法中,我们可以看到认证由这句代码完成
info = this.authenticate(token);
authenticate方法来自一个抽象类AuthenticatingSecurityManager,它是SessionsSecurityManager的祖父类,该类中有一个属性:
private Authenticator authenticator = new ModularRealmAuthenticator();
方法:
public AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException { return this.authenticator.authenticate(token); }
此处的authenticator就是AbstractAuthenticator,它的authenticate方法,该方法内部再调用doAuthenticate(token)
,它由AbstractAuthenticator的子类ModularRealmAuthenticator来实现,此处就开始出现数据库交互的Realm:
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException { this.assertRealmsConfigured(); //此处已经出现了执行数据库交互的Realm Collection<Realm> realms = this.getRealms(); //检查realm集合的尺寸大小,如果只有一个,那么执行doSingle...(,) return realms.size() == 1 ? this.doSingleRealmAuthentication((Realm)realms.iterator().next(), authenticationToken) : this.doMultiRealmAuthentication(realms, authenticationToken); }
doSingleRealmAuthentication((Realm)realms.iterator().next(), authenticationToken):
protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token) {//检查传入的token是否属于支持的类型,不支持则抛出异常 if (!realm.supports(token)) { String msg = "Realm [" + realm + "] does not support authentication token [" + token + "]. Please ensure that the appropriate Realm implementation is " + "configured correctly or that the realm accepts AuthenticationTokens of this type."; throw new UnsupportedTokenException(msg); } else { //如果支持,则调用realm的getAuthenticationInfo方法 AuthenticationInfo info = realm.getAuthenticationInfo(token); if (info == null) { String msg = "Realm [" + realm + "] was unable to find account data for the " + "submitted AuthenticationToken [" + token + "]."; throw new UnknownAccountException(msg); } else { return info; } } }
关于Realm的getAuthenticationInfo方法,它的内部又调用了doGetAuthenticationInfo(token),这是一个十分眼熟的方法,眼熟的原因在于,我们的自定义Realm就需要重写该方法。
所以,总结一下整个流程,就是,在我们调用currUser的login方法之后,它经历过一系列的步骤,调用了Realm中我们所定义的doGetAuthenticationInfo(token)方法,获取了一个AuthenticationInfo对象,该info或许是null,或者是提取到数据库数据之后创建的对象 ,在此之后就是之前Realm篇谈到的关于token和info比对的过程,这个过程我们再复习一遍,它是在AuthenticatingRealm中有一个assertCredentialsMatcher(token,info)的操作,该操作事实上又调用了HashedCreadentialsMatecher(这里因为我们在spring中的realm配置的是该加密器)的doCredentialsMatcher(token,info)方法。
在这个流程中,重点可以记住,是ModularRealmAuthenticator完成了我们调用Realm的操作。
- Shiro认证源码解析和工作原理
- 安全认证框架Shiro (二)- shiro过滤器工作原理
- Shiro身份认证流程,securityManager源码解析
- shiro认证源码
- Shiro安全框架的登陆认证源码解析
- 注解工作原理源码解析
- Android AsyncTask 源码详细解析,掌握工作原理和细节
- 安全认证框架Shiro(三)- 源码角度解析shiro的权限验证
- shiro 权限框架认证和授权原理介绍
- shiro 认证filter 的原理
- shiro认证授权源码分析
- Shiro 登录认证源码详解
- Shiro源码分析----认证流程
- Shiro源码分析----认证流程
- Servlet工作原理以及源码解析
- Android源码解析AsyncTask的工作原理
- Android 源码解析AsyncTask的工作原理
- shiro原理解析
- ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this ..
- 执行hadoop jar命令时报Not a valid JAR的原因分析和解决方案
- Android 应用开发性能优化之UI卡顿
- java GridBagConstraints解析
- 安装Hbase(分布式)遇到一些问题及解决方法
- Shiro认证源码解析和工作原理
- BlobCache算法
- Android 应用开发性能优化之UI卡顿分析及解决方法
- 数学与持久战
- 【Java】Switch-case的一些小总结
- linux知识包
- Spring--Java配置
- 给OD扩展功能示例
- javascript深入理解js闭包