Shiro源代码分析之两种Session的方式
1、Shiro默认的Session处理方式
<!-- 定义 Shiro 主要业务对象 --> |
这里从DefaultWebSecurityManager这里看起。这个代码是定义的Shiro安全管理对象,看以下的构造方法(代码
1-1)
(代码 1-1) public DefaultWebSecurityManager() { |
从 构造方法里面能够看出,这里面有 publicvoid setRememberMeManager(RememberMeManager rememberMeManager)
和 publicvoid setSessionManager(SessionManager sessionManager)两个方法。这两个各自是对Shiro的remembereMe功能和Session功能的管理。当中在构造方法里面能够看到,事实上一开是就设置了SessionManager。就是默认的:ServletContainerSessionManager().接下来看看默认的ServletContainerSessionManager()是怎么玩转Session的.看下图。这个图显示了这个类的这些个方法
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
这个类通过getSession(SessionKey)获得Sesison,以下看看这种方法干了些什么(代码1-2)
(代码1-2) publicSession getSession(SessionKey key) throws SessionException { if (!WebUtils.isHttp(key)) { //推断是不是http的key,否则抛异常 |
能够看看凝视,凝视上都写好了。这里的意思是。首先推断封装好的Key是不是Http的key。假设是就继续,不是就抛异常.key这个是带了ServletRequest和ServletResponse的WebSessinKey,详细怎么new出来的,看DefaultWebSecurityManager的这方法代码就知道了(代码1-3)。这里里,将Request和Response还有sessionId传递进去
(代码1-3) @Override protected SessionKey getSessionKey(SubjectContext context) { |
由于继承了 org.apache.shiro.session.mgt.DefaultSessionKey ,这个类是实现了SessionKey这个接口。 看看createSession这种方法,这种方法就是将传入的HttpSession和host传进去,封装成Shiro的HttpServletSession (代码 1-4)
(代码1-4) protectedSession createSession(HttpSession httpSession, String host) { return new HttpServletSession(httpSession, host); |
关于默认的Session管理器,最后还看一下HttpServletSession这个类。就看一下的几个方法。还有些方法是没有放出来的,能够明显的看出。Shiro使用了一个叫Session的接口。但这个接口是和HttpSession的接口一模一样。就是通过HttpSession这个接口获得Session的功能(代码1-5)
(代码1-5) public class HttpServletSession implements Session { |
默认的模式就描写叙述到这里
2、接下来说另外一种方式。就是废弃掉tomcat自己的Session,使用企业级Session方案。这样的方案能够和容器无关。但在我们项目没有使用,由于用了开源连接池druid貌似logout的时候有点不正确。
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="globalSessionTimeout" value="3600000" />
<property name="sessionDAO" ref="sessionDAO" />
</bean>
<bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
<property name="activeSessionsCacheName" value="shiro-activeSessionCache" />
<property name="cacheManager" ref="shiroCacheManager" />
</bean> <!-- 用户授权信息Cache, 採用EhCache -->
<bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManager" ref="cacheManager"/>
</bean>
必须向Spring注冊EnterpriseCacheSessionDAO然后将cacheManager注入进去
这样的配置的创建入口在SecurityUtils.getSubject().getSession();这里看以下代码(代码2-1)
(代码2-1) publicSession getSession(boolean create) { if (log.isTraceEnabled()) { |
调用DefaultSecurityManager的父类SessionsSecurityManager的Sessionstart(SessionContext
context)。以下是这种方法的代码(代码2-2)
(代码2-2) public Session start(SessionContext context) throws AuthorizationException { |
然后调用sessionManager的start方法来创建Session。创建Session的入口。就在这里。看以下代码分析(代码2-3)
(代码2-3) publicSession start(SessionContext context) { Session session = createSession(context);//创建Session |
创建Session这里是调用DefaultSessionManager的父类的createSession,事实上父类也没有真正来创建Session。
这里用到了模板方法。父类里面的doCreateSession是抽象方法,最后真正创建子类的还是交给子类去实现(代码2-4)
(代码2-4) protectedSession createSession(SessionContext context) throwsAuthorizationException { enableSessionValidationIfNecessary(); |
其它的也没多少可分析的。这里再看一下manager里面的sessionFacotry工厂的createSession方法(代码2-5)
(代码2-5) publicSession createSession(SessionContext initData) { if (initData != null) { |
这里的SimpleSession是实现了Session接口的。详细能够看看相关的类继承图
另外Session是怎么缓存进入Cache的呢?在以下的调用以下代码创建Session的过程中,以下方法会调用,而缓存就在create(s)这里面(代码2-6)
(代码2-6) protected Session doCreateSession(SessionContext context) { |
经过一些步骤之后在CachingSessionDao里被缓存,以下是代码。
能够看以下的凝视(代码2-7)
(代码2-7) protectedvoid cache(Session session, Serializable sessionId) { if (session == null || sessionId == null) { |
以上是Session的创建过程,获取Session就简单说吧。有些过程自己发现更有趣。这里会调用DefaultWebSessionManager的父类的getAttribute这种方法(代码2-8)
(代码2-8) publicObject getAttribute(SessionKey sessionKey, Object attributeKey)throws InvalidSessionException { return lookupRequiredSession(sessionKey).getAttribute(attributeKey); |
最后会调用CachingSessionDao的这个publicSession readSession(Serializable
sessionId) throwsUnknownSessionException 在这里就会从缓存里读取Session(代码2-9)
(代码2-9) public Session readSession(Serializable sessionId) throws UnknownSessionException { |
这是getCachedSession(sessionId)的代码。看了代码想必非常easy理解了吧(代码2-10)
protected Session getCachedSession(Serializable sessionId) { |
获得了Session,要获得里面的值和对象就非常easy了
有问题欢迎提出来。由于是先写在编辑器上的。然后在复制到word上。所以代码是一致的黑色,希望可以讲究着看,写个原创文章不easy,眼睛都看肿了。所以转载的时候能带上作者,谢谢
作者:肖华
blog.csdn.net/xh199110
飞丶天
Shiro源代码分析之两种Session的方式的更多相关文章
- 牛客网Java刷题知识点之Map的两种取值方式keySet和entrySet、HashMap 、Hashtable、TreeMap、LinkedHashMap、ConcurrentHashMap 、WeakHashMap
不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...
- 关于VAD的两种内存隐藏方式
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html 技术学习来源:火哥(QQ:471194425) 内存在0环的两种内 ...
- Windows Azure VM的两种shut down 方式
今天在调查Azure的价格时,发现下面的语句,来自http://azure.microsoft.com/en-us/pricing/details/virtual-machines/ * If my ...
- 两种隐藏元素方式【display: none】和【visibility: hidden】的区别
此随笔的灵感来源于上周的一个面试,在谈到隐藏元素的时候,面试官突然问我[display: none]和[visibility: hidden]的区别,我当时一愣,这俩有区别吗,好像有,但是忘记了啊,因 ...
- Linux共享库两种加载方式简述
Linux共享库两种加载方式简述 动态库技术通常能减少程序的大小,节省空间,提高效率,具有很高的灵活性,对于升级软件版本也更加容易.与静态库不同,动态库里面的函数不是执行程序本身 的一部分,而是 ...
- android环境下两种md5加密方式
在平时开发过程中,MD5加密是一个比较常用的算法,最常见的使用场景就是在帐号注册时,用户输入的密码经md5加密后,传输至服务器保存起来.虽然md5加密经常用,但是md5的加密原理我还真说不上来,对md ...
- Form表单中method=post/get两种数据传输的方式的区别
Form提供了两种数据传输的方式——get和post.虽然它们都是数据的提交方式,但是在实际传输时确有很大的不同,并且可能会对数据产生严重的影响.虽然为了方便的得到变量值,Web容器已经屏蔽了二者的一 ...
- 两种数据传输的方式——get和post。
Form提供了两种数据传输的方式——get和post.虽然它们都是数据的提交方式,但是在实际传输时确有很大的不同,并且可能会对数据产生严重的影响.虽然为了方便的得到变量值,Web容器已经屏蔽了二者的一 ...
- Xamarin Android Fragment的两种加载方式
android Fragment的重点: 3.0版本后引入,即minSdk要大于11 Fragment需要嵌套在Activity中使用,当然也可以嵌套到另外一个Fragment中,但这个被嵌套的Fra ...
随机推荐
- Hdu 3177 (贪心)
题目大意: 山洞的体积为\(v\) 第\(i\)个物品放在山洞里会占据\(a_i\)的空间,在搬运过程中至少需要\(b_i\)的空间 问能不能把所有物品都放下 贪心题.比较难看出贪心,但是从无顺序要求 ...
- Day10文件内指针移动和函数
强调:只有t模式下的read(n),n代表字符个数,除此以外都是以字节为单位 ,例如f.read(4)读出4个字符 控制文件内指针的移动:f.seek()以字节为单位 f.tell()文件开头为准,当 ...
- centos7 安装nodejs 最新版
笔者在安装时,node为11.0.0版本.这里以11版本为例,以后更新,安装步骤时一致的. 下载node安装包到指定目录 wget https://npm.taobao.org/mirrors/nod ...
- iOS 唯一标示符 卸载后安装值不变
Vindor标示符 (IDFV-identifierForVendor) 这种叫法也是在iOS 6中新增的,不过获取这个IDFV的新方法被添加在已有的UIDevice类中.跟advertisingId ...
- DefaultActionInvocation 源码
/** * Copyright 2002-2006,2009 The Apache Software Foundation. * * Licensed under the Apache License ...
- 【UML】9种图+包图
导读:在UML的学习中,介绍了9种图,外加一个包图.这9种图和4大关系,可以说是UML的一个核心内容.我根据自己的笔记,以及查阅的一些资料,对这9种图和包图,做一个总结. 一.基本定义 1.1 总体 ...
- 【bzoj2989】数列 KD-tree+旋转坐标系
题目描述 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]|. 2种操作(k都是正整数): 1.Mo ...
- [BZOJ4993||4990] [Usaco2017 Feb]Why Did the Cow Cross the Road II(DP + 线段树)
传送门 f[i][j]表示当前第i个,且最后一个位置连接到j 第一维可以省去,能连边的点可以预处理出来,dp可以用线段树优化 #include <cstdio> #include < ...
- 刷题总结——赛车(bzoj3190)
题目: 题目背景 JLOI2013 T1 题目描述 这里有一辆赛车比赛正在进行,赛场上一共有 N 辆车,分别称为 g1,g2,……,gn.赛道是一条无限长的直线.最初,gi 位于距离起跑线前进 ki ...
- 【bzoj1854】[Scoi2010]游戏 - 并查集
lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备最多只能使 ...