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 ...
随机推荐
- webpack-dev-server proxy代理
一个最简单的代理例子:index.html中有如下代码 fetch('/api/pub/article/list?pageSize=2').then((data)=>{ return data. ...
- Linux文件权限与文件夹权限实践
文件权限在基础中有介绍,不在重复 一.文件夹权限: 示例: 解释说明: r --read 既ls w --write 既创建新的目录或者文件 x --execute 既cd 现在有4个用户分属 ...
- 9-Python基础知识-day1
Python基础知识-day1 Python 2 和Python 3 的区别: Python2 源码不标准,混乱,重复代码多:#-*-encoding:utf8 -*- 解决python2显示中文的问 ...
- Hi3519V101 SDK安装以及开发环境搭建
Hi3519V101 Linux开发环境 1.安装Hi3519V101 SDKHi3519V101 SDK是基于Hi3519V101 DMEB的软件开发包,包含了在Linux相关应用开发时使用的各种工 ...
- Ubuntu 16.04上thunderbird配置163邮箱出现“配置无法被验证-请查看用户名或密码是否正确?”
在Ubuntu 16.04 上用thunderbird配置163免费邮箱时出现的提示信息如图1: 图1 提示信息 网上有不少方法都说是将接收和发出的主机名分别改为 imap.ym.163.com 和 ...
- java读写串口数据
本博文参考自https://www.cnblogs.com/Dreamer-1/p/5523046.html 最近接触到了串口及其读写,在此记录java进行串口读写的过程. 1.导入串口支持包 需要下 ...
- PYDay4-基本数据类型、字符串、元组、列表、字典
1.关于编码: utf-8 与gbk都是对Unicode 编码的简化,utf-8是针对所有语言的精简,gbk是针对中文的精简 py3默认字符集为UTF-8,取消了Unicode字符集,如后面的编程过程 ...
- SQL server将查询到的多行结果,拼接成字符串(列转行)
select stuff(( ,,'') as UserNamestr 注释:查询出tabname表中的UserName列的所有内容,并将内容拼接成UserNamestr
- CentOS7搭建Maven的Nexus私服仓库
1.下载nexus 打开一下链接: https://www.sonatype.com/nexus-repository-oss 下载安装包. 2.解压安装包 tar zxvf nexus-3.9.0- ...
- PHP 判断表单提交的file是否为空
echo '<pre>'; var_dump($product_attach_files); echo "</pre>"; echo ];