先行回顾一下使用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实例以及一个token
public 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();//此处已经出现了执行数据库交互的RealmCollection<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认证源码解析和工作原理相关推荐

  1. 顺序线性表 ---- ArrayList 源码解析及实现原理分析

    原创播客,如需转载请注明出处.原文地址:http://www.cnblogs.com/crawl/p/7738888.html ------------------------------------ ...

  2. .Net Core 认证系统之基于Identity Server4 Token的JwtToken认证源码解析

    介绍JwtToken认证之前,必须要掌握.Net Core认证系统的核心原理,如果你还不了解,请参考.Net Core 认证组件源码解析,且必须对jwt有基本的了解,如果不知道,请百度.最重要的是你还 ...

  3. vuex 源码分析_vue源码解析之vuex原理

    常用接口 dispatch 操作行为触发方法,是唯一能执行action的方法. actions 操作行为处理模块.负责处理Vue Components接收到的所有交互行为.包含同步/异步操作,支持多个 ...

  4. Spring Cloud Hystrix 源码系列:工作原理

    Hystrix 译为 "豪猪",豪猪的棘刺能保护自己不受天敌伤害,代表了强大的防御能力.Hystrix 基于 RxJava 进行实现,RxJava 是一种基于观察者模式的响应式编程 ...

  5. java校验框架源码解析_Spring Boot原理剖析和源码分析

    Spring Boot原理剖析和源码分析 依赖管理 问题一:为什么导入dependency时不需要指定版本? spring-boot-starter-parent依赖 org.springframew ...

  6. vue 存储对象 不要监听_Vue源码解析----响应式原理

    从很久之前就已经接触过了angularjs了,当时就已经了解到,angularjs是通过脏检查来实现数据监测以及页面更新渲染.之后,再接触了vue.js,当时也一度很好奇vue.js是如何监测数据更新 ...

  7. VUE源码解析-响应式原理的实现

    前言 相信vue学习者都会发现,vue使用起来上手非常方便,例如双向绑定机制,让我们实现视图.数据层的快速同步,但双向绑定机制实现的核心数据响应的原理是怎么样的呢,接下来让我们开始介绍: functi ...

  8. 云原生服务网格Istio:原理、实践、架构与源码解析

    华为云原生团队600多页的Istio实战精华总结,云原生服务网格Istio:原理.实践.架构与源码解析的电子书. 图书介绍 <云原生服务网格Istio:原理.实践.架构与源码解析>分为原理 ...

  9. Dubbo 实现原理与源码解析系列 —— 精品合集

    摘要: 原创出处 http://www.iocoder.cn/Dubbo/good-collection/ 「芋道源码」欢迎转载,保留摘要,谢谢! 1.[芋艿]精尽 Dubbo 原理与源码专栏 2.[ ...

最新文章

  1. java中sax的使用_java使用sax对xml文档的解析
  2. MySQL解压版配置
  3. jQuery 1.9使用$.support替代$.browser的使用方法
  4. linux字符设备开发
  5. leetcode 684. Redundant Connection | 684. 冗余连接(并查集)
  6. Redis cluster集群模式的原理
  7. vue如何获取年月日_BootstrapVue——Vue和Bootstrap的相结合,构建响应式应用更简单...
  8. 使用反应流作为Drools的数据源
  9. c++ const限定符
  10. API功能测试如何实施(转载自测试之道 微信公众号)
  11. 本地Windows安装MySQL
  12. 七牛sdk 上传视频 - 前端
  13. 浅谈一下量化交易与程序化交易
  14. 暴雪插件占用服务器,你还在用这款插件吗?暴雪公布《魔兽世界》怀旧服卡顿原因...
  15. DEEPCON: protein contact prediction using dilated convolutional neural networks with dropout
  16. [codeforces 1312A] Two Regular Polygons 整除
  17. SpringSecurity---细粒度的权限控制
  18. 网格平滑基础算法总结
  19. 丢包是啥意思?如何排查丢包原因呢?
  20. 数据分析---论文数据统计

热门文章

  1. “热榜第一”阿里年薪80W的Java架构师,到底是有着怎样的水平?
  2. 小米品牌升级,启用新LOGO
  3. Webservice简介
  4. BitmapFactory压缩图片
  5. 200-Smart学习笔记:比较传送移位指令的用法案例(3)
  6. 周周周报报报(药店管理系统)
  7. 页面提交成功后,弹窗提示
  8. 人口统计、红利、康波
  9. 帝国织梦和各种php网页将局部广告进行屏蔽搜索引擎蜘蛛
  10. Apache PHP 的gzip压缩输出的实现方法