欢迎光临
我们一直在努力

shiro实现无状态的会话,带源码分析

转载请在页首明显处注明作者与出处

朱小杰      http://www.cnblogs.com/zhuxiaojie/p/7809767.html

 

 

一:说明

在网上都找不到相关的信息,还是翻了大半天shiro的源码才找到答案。亲试绝对可行,带源码分析

 

很多时候,开发的项目不仅仅是一个基于浏览器的项目,还可能是基于app的项目,基于小程序的项目,而这些项目都是无状态的。而普通web项目中,一个web项目的会话是由session保持的,而session又是由浏览器携带的cookie来验证身份的,可以这么说,一个会话就是依赖于cookie,但是app与小程序是没有cookie维持的。

  一般的作法会在header中带有一个token,或者是在参数中,后台根据这个token来进行校验这个用户的身份,但是这个时候,servlet中的session就无法保存,我们在这个时候,就要实现自己的会话创建,普通的作法就是重写session与request的接口,然后在过滤器在把它替换成自己的request,所以得到的session也是自己的session,然后根据token来创建和维护会话。

  但在shiro中会怎么做呢?

 

 

 

 

 

二:shiro介绍

  shiro是一个权限验证框架,它比spring security的功能要少一些,但是我却更喜欢shiro,因为spring security封装的太死了,如果要重写一些功能,特别的麻烦,而shiro中使用了大量的策略模式,使得开发人员可以很好的替换成自己的策略,灵活性更加强,可以定义自己的过滤器来实现自己需要的一些功能。

 

shiro中的权限操作是委托给securityManager的,而securityManager管理session又是委托给sessionManager的,在开发web项目中,我们一般会使用

来创建securityManager,我们看一下这个DefaultWebSecurityManager默认是使用的哪个session管理器,它的构造方法如下

可以看到,如果构造一个DefaultWebSecurityManager,它使用的是

它是依赖于浏览器的cookie来维护session的,那肯定不能实现无状态的会话。

 

 

 

不过shiro还提供了另一个基于web的session管理器,它就是

如果我们想实现自己的一套session管理器,都会选择去继承它来重写

 

小提示:笔者1.4.0的版本,当前是最新版本,无法直接在security中设置sessionManager的时候,直接new一个DefaultWebSessionManager,如下:

 

 

如果直接设置为DefaultWebSessionManager,那么在有http请求的时候会报错,提示找不到SecurityManager,解决办法是写一个类来继承它,哪怕继承后什么都不做,都可以解决这个问题

 

 

 

 

 

 

三:重写shiro的sessionManager

上面说到我们要重写DefaultWebSessionManager,那我们要怎么重写呢?

 

 

 

 

 

 

 

 

 

 

 

三:源码分析

 

 

上面就是完整的重写的代码,我们一个一个方法来看

 

 

这个方法的覆盖和它的父类其实没有太大的区别,逻辑上面都是通过一个sessionKey来获取一个sessionid,但是重写的部分多了一个把获取到的token设置到request的部分,这是因为app调用登陆接口的时候,是没有token的,登陆成功后,产生了token,我们把它放到request中,返回结果给客户端的时候,把它从request中取出来,并且传递给客户端,客户端每次带着这个token过来,就相当于是浏览器的cookie的作用,也就能维护会话了

 

这里不得不说一下sessionId和sessionKey的区别了,本人也是因为这个东西坑了好久,从字面上面看,sessionKey是一个对象,而sessionId是一个serializable对象,实际上从我们返回的token可以知道,它就是一个String。

 

sessionKey是在sessionStore中,对应存储的key值,而sessionId则就是请求带来的token,或者是浏览器请求的cookie中的jsessionid。

 

我们要想象一个,他们有什么关系呢?我们通过sessionId,应该得到sessionKey,然后通过sessionKey,能在sessionStore中找到session,那我们就把sessionId与sessionKey相等吧,这样就不用找对应关系了,因为sessionId就等于sessionKey的话,那我们也不需要保存他们之间的对应关系了,而其实DefaultWebSessionManager也是这样做的,因数sessionKey这个对象里面就有一个sessionId。

 

但是有一个值得注意的是,这个方法会被调用多次,用户登陆成功以后,会话保持成功后,怎么调用,传入的sessionKey都是一样的,但是我们把镜头拉到用户登陆的那一次请求中,就会发现一些不同的地方了。

 

  我们可以看到,第一次调用时,sessionKey里面的sessionId是空的,按照我们的逻辑,我们会调用第二个方法,取得header中的token,然后返回sessionId为token。

  断点继续,第二次调用的时候,也会传入一个sessionKey,但是这个sessionKey里面的sessionId值却已经有了,它是一个uuid,但是sessionKey里面的sessionId,与第一次返回的sessionId不一致,或者说和我们的token不一致,这是为什么呢?

  因为当得到sessionId时,session管理器会尝试到sessionStore中通过这个sessionKey去获取一个session,但是可以肯定的是,这个session肯定是得不到的,因为还没有代码给它创建,所以当检测到获取到的session为null的时候,会调用sessionStore的createSession方法,这个时候,它会生成一个随机的sessionId,然后根据这个新生成的sessionId,创建一个session,然后会把这个sessionId设置到sessionKey里面,替换掉之前的sessionId,所以我们在这个方法后面的几次调用就就会发现第一次不一样,sessionId也和第一次返回的sessionId不一样,因为它创建session的时候生成了一个新的sessionId,这个时候我们要怎么办呢?

 

 

我们就修改客户端的token,让它与最新生成的sessionId一致就行了,所以之前说的,这里面有一个把token设置到request中的代码,就是在返回给客户端的时候,通知给客户端最新的token,而不是继续沿用之前的token,因为这个token在sessionStore中是没法取出一个session的。

 

还有一个要注意的地方,我们从request取出新的token返回给客户端的时候,要在认证完成之后,因为只有当认证完成之后,才会创建session,才会得到最新的token并返回给客户端,不然返回的是老的token。

代码如下:

 

 

 

我们把token返回给客户端,然后客户端每次请求时,带上这个token,我们就维持这个会话了

 

 

 

 

 

方法签名如下

 

 

 

第二个方法相对简单,因为仅仅是获取token而已,可以从header获取,参数中获取,cookie中获取,当然用户第一次请求的时候,肯定是没有token的,只有登陆成功后才会得到token,所以当token为null的时候,我们生成了一个uuid,但是这个uuid并不会成为后面的token,这个在上面有讲到,因为会被后面生成session时生成的sessionId给替换掉。

 

而至少那一堆设置数据到request中的代码,我也没去看具体做什么用的,因为它的父类中,执行这个方法的时候,有这些代码的设置,复制过来,怕出什么问题。

 

 

 

 

 

 

四:完整配置代码

 

完整的配置代码如下:

 

 

 

 

 

 

 

其实完整的配置代码都已经不重要了,重要的就是sessionManager,上面红色部分说明了怎么把我们自己写的sessionManager设置到securityManager中。

 

  • 海报
海报图正在生成中...
赞(0) 打赏
声明:
1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。
2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。
3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。
4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。
文章名称:《shiro实现无状态的会话,带源码分析》
文章链接:https://www.456zj.com/20164.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址