欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

shiro源码篇 - shiro的session管理,你值得拥有

程序员文章站 2022-06-02 23:22:45
前言 开心一刻 开学了,表弟和同学因为打架,老师让他回去叫家长。表弟硬气的说:不用,我打得过他。老师板着脸对他说:和你打架的那位同学已经回去叫家长了。表弟犹豫了一会依然硬气的说:可以,两个我也打得过。老师:...... 路漫漫其修远兮,吾将上下而求索! github:https://github.c ......

前言

  开心一刻

    开学了,表弟和同学因为打架,老师让他回去叫家长。表弟硬气的说:不用,我打得过他。老师板着脸对他说:和你打架的那位同学已经回去叫家长了。表弟犹豫了一会依然硬气的说:可以,两个我也打得过。老师:......

 

  路漫漫其修远兮,吾将上下而求索!

  github:

  码云(gitee):

前情回顾

  大家还记得讲了什么吗,我们来一起简单回顾下:

    httpservletrequestwrapper是httpservletrequest的装饰类,我们通过继承httpservletrequestwrapper来实现我们自定义的httpservletrequest:customizesessionhttpservletrequest,重写customizesessionhttpservletrequest的getsession,将其指向我们自定义的session。然后通过filter将customizesessionhttpservletrequest添加到filter chain中,使得到达servlet的servletrequest是我们的customizesessionhttpservletrequest。

  今天不讲session共享,我们先来看看shiro的session管理

securitymanager

  securitymanager,安全管理器;即所有与安全相关的操作都会与securitymanager交互;它管理着所有subject,所有subject都绑定到securitymanager,与subject的所有交互都会委托给securitymanager;securitymanager是shiro的核心,它负责与shiro的其他组件进行交互,类似springmvc中的dispatcherservlet或struts2中的filterdispatcher。

  我们在使用shiro的时候,首先都会先初始化securitymanager,然后往securitymanager中注入shiro的其他组件,像sessionmanager、realm等。我们的中初始化的是defaultwebsecuritymanager,如下

shiro源码篇 - shiro的session管理,你值得拥有
@bean
public securitymanager securitymanager(authorizingrealm myshirorealm, cachemanager shirorediscachemanager) {
    defaultwebsecuritymanager securitymanager = new defaultwebsecuritymanager();
    securitymanager.setcachemanager(shirorediscachemanager);
    securitymanager.setremembermemanager(cookieremembermemanager());
    securitymanager.setrealm(myshirorealm);
    return securitymanager;
}
view code

  securitymanager类图

    结构如下,认真看看,注意看下属性

shiro源码篇 - shiro的session管理,你值得拥有

    顶层组件securitymanager直接继承了sessionmanager且提供了sessionssecuritymanager实现,sessionssecuritymanager直接把会话管理委托给相应的sessionmanager;securitymanager的默认实现:defaultsecuritymanager及defaultwebsecuritymanager都继承了sessionssecuritymanager,也就是说:默认情况下,session的管理由defaultsecuritymanager或defaultwebsecuritymanager中的sessionmanager来负责

    defaultsecuritymanager

      默认安全管理器,用于我们的javase安全管理,一般而言用到的少,但我们需要记住,万一哪次有这个需求呢。

      我们来看下他的构造方法

shiro源码篇 - shiro的session管理,你值得拥有

      默认的sessionmanager是defaultsessionmanager,defaultsessionmanager具体详情请看下文。

    defaultwebsecuritymanager

      默认web安全管理器,用于我们的web安全管理;一般而言,我们的应用中初始化此安全管理器。

      我们来看看其构造方法

shiro源码篇 - shiro的session管理,你值得拥有

shiro源码篇 - shiro的session管理,你值得拥有
public defaultwebsecuritymanager() {
    super();                                                    // 会调用sessionssecuritymanager的构造方法,实例化defaultsessionmanager
    ((defaultsubjectdao) this.subjectdao).setsessionstorageevaluator(new defaultwebsessionstorageevaluator());
    this.sessionmode = http_session_mode;
    setsubjectfactory(new defaultwebsubjectfactory());
    setremembermemanager(new cookieremembermemanager());
    setsessionmanager(new servletcontainersessionmanager());    // 设置sessionmanager,替换掉上面的defaultsessionmanager
}
view code

      可以看出此时的sessionmanager是servletcontainersessionmanager,servletcontainersessionmanager具体详情请看下文。

    由此可知默认情况下,defaultsecuritymanager会将session管理委托给defaultsessionmanager,而defaultwebsecuritymanager则将session管理委托给servletcontainersessionmanager。

    我们可以通过继承defaultsecuritymanager或defaultwebsecuritymanager来实现自定义securitymanager,但一般而言没必要,defaultsecuritymanager和defaultwebsecuritymanager基本能满足我们的需要了,我们根据需求二选其一即可。无论defaultsecuritymanager还是defaultwebsecuritymanager,我们都可以通过setsessionmanager方法来指定sessionmanager,如果不指定sessionmanager的话就用的securitymanager默认的sessionmanager。

sessionmanager

  shiro提供了完整的会话管理功能,不依赖底层容器,javase应用和javaee应用都可以使用。会话管理器管理着应用中所有subject的会话,包括会话的创建、维护、删除、失效、验证等工作。

  sessionmanager类图

shiro源码篇 - shiro的session管理,你值得拥有

      defaultsessionmanager

      defaultsecuritymanager默认使用的sessionmanager,用于javase环境的session管理。

shiro源码篇 - shiro的session管理,你值得拥有

      通过上图可知(结合securitymanager类图),session创建的关键入口是sessionssecuritymanager的start方法,此方法中会将session的创建任务委托给具体的sessionmanager实现。

      defaultsessionmanager继承自abstractnativesessionmanager,没用重写start方法,所以此时abstractnativesessionmanager的start方法会被调用,一路往下跟,最终会调用defaultsessionmanager的docreatesession方法完成session的创建,docreatesession方法大家可以自行去跟下,我在这总结一下:       

        创建session,并生成sessionid,session是shiro的simplesession类型,sessionid采用的是随机的uuid字符串;
        sessiondao类型是memorysessiondao,session存放在sessiondao的private concurrentmap<serializable, session> sessions;属性中,key是sessionid,value是session对象;
        除了memorysessiondao,shiro还提供了enterprisecachesessiondao,具体两者有啥区别请看我的讲解。

    servletcontainersessionmanager

      defaultwebsecuritymanager默认使用的sessionmanager,用于web环境,直接使用的servlet容器的会话,具体实现我们往下看。

      servletcontainersessionmanager实现了sessionmanager,并重写了sessionmanager的start方法,那么我们从servletcontainersessionmanager的start方法开始来看看session的创建过程,如下图

shiro源码篇 - shiro的session管理,你值得拥有

      shiro有自己的httpservletsession,httpservletsession持有servlet的httpsession的引用,最终对httpservletsession的操作都会委托给httpsession()。那么此时的session是标准servlet容器支持的httpsession实例,它不与shiro的任何与会话相关的组件(如sessionmanager,securitymanager等)交互,完全由servlet容器管理。

    defaultwebsessionmanager

      用于web环境,可以替换servletcontainersessionmanager,废弃了servlet容器的会话管理;通过此可以实现我们自己的session管理;

      从sessionmanager类图可知,defaultwebsessionmanager继承自defaultsessionmanager,也没有重写start方法,那么创建过程还是沿用的abstractnativesessionmanager的start方法;如果我们没有指定自己的sessiondao,那么session还是存在memorysessiondao的concurrentmap<serializable, session> sessions中,具体可以看上述中的defaultsessionmanager。

      通过defaultwebsessionmanager实现session共享,尽请期待!

总结

  两个类图

    securitymanager和sessionmanager的类图需要认真看看;

    subject的所有交互都会委托给securitymanager;securitymanager是shiro的核心,它负责与shiro的其他组件进行交互,类似springmvc中的dispatcherservlet或struts2中的filterdispatcher;

    securitymanager会将session管理委托给sessionmanager;sessionssecuritymanager的start方法中将session的创建委托给了具体的sessionmanager,是创建session的关键入口。
  shiro的simplesession与httpservletsession
    httpservletsession只是servlet容器的session的装饰,最终还是依赖servlet容器,是shiro对servlet容器的session的一种支持;
    而simplesession是shiro完完全全的自己实现,是shiro对session的一种拓展。

参考

  《跟我学shiro》