zoukankan      html  css  js  c++  java
  • Shiro官方快速入门10min例子源码解析框架2-Session

    Shiro自身维护了一套session管理组件,它可以独立使用,并不单纯依赖WEB/Servlet/EJB容器等环境,使得它的session可以任何应用中使用

    2-Session)主要介绍在quickstart例子中从获取Subject后,由初始化获取Session写入读出session参数的完整过程。

    同样,本篇本文使用的是shiro 1.3.2版本,配合源码最佳~

    psr5wpkh

    Shiro自身提供了SessionManager的三种实现来支持不同的模式

    DefaultSessionManager:Shiro自身维护的session,可在普通应用环境使用

    DefaultWebSessionManager:独立提供在shiro-web包中,继承SessionManager,并额外支持WEB相关方法

    ServletContainerSessionManager:使用Servlet容器提供Session管理,提供少量额外方法

    vdq5frmh

    在samples-quickstart例子中使用到的是DefaultSessionManager。

     

    篇1(Shiro官方快速入门10min例子源码解析框架1-初始化)中,1.2节DefaultSecurityManager是DefaultSessionManager的子类,在初始化DefaultSecurityManager时一同初始化DefaultSessionManager

    在获取到Subject后,继续看samples-quickstart的代码如何获取和设置Session

    Subject currentUser = SecurityUtils.getSubject();

    2.1下一步是获取Session,调用Subject的getSession方法

    Session session = currentUser.getSession();

    DelegatingSubject中,getSession()若无参数,则调用getSession(true),如果不需要Shiro 的Session功能可以调用getSession(false),

    public Session getSession() {
            return getSession(true);
        }

    调用DelegatingSubject.getSession(true),前半部分是日志,及isSessionCreationEnabled()判断(默认为ture)

    public Session getSession(boolean create) {
            if (log.isTraceEnabled()) {
                log.trace("attempting to get session; create = " + create +
                        "; session is null = " + (this.session == null) +
                        "; session has id = " + (this.session != null && session.getId() != null));
            }
    
            if (this.session == null && create) {
    
                //added in 1.2:
                if (!isSessionCreationEnabled()) {
                    String msg = "Session creation has been disabled for the current subject.  This exception indicates " +
                            "that there is either a programming error (using a session when it should never be " +
                            "used) or that Shiro's configuration needs to be adjusted to allow Sessions to be created " +
                            "for the current Subject.  See the " + DisabledSessionException.class.getName() + " JavaDoc " +
                            "for more.";
                    throw new DisabledSessionException(msg);
                }
    
                log.trace("Starting session for host {}", getHost());
                SessionContext sessionContext = createSessionContext();
                Session session = this.securityManager.start(sessionContext);
                this.session = decorate(session);
            }
            return this.session;
        }

    主要在后半部分sessionContext、session获取,及decorate过程

    l0gzso40

    2.1.1获取默认空白sessonContext,其为map的子类,

    2.1.2构建session将sessionContext绑定到其中

    2.1.3包装session

    2.1.2调用SessionsSecurityManager.start 其中sessionManager是DefaultSessionManager的实例

    public Session start(SessionContext context) throws AuthorizationException {
            return this.sessionManager.start(context);
        }

    其调用父类AbstractNativeSessionManager中的start方法

    public Session start(SessionContext context) {
            Session session = createSession(context);
            applyGlobalSessionTimeout(session);
            onStart(session, context);
            notifyStart(session);
            //Don't expose the EIS-tier Session object to the client-tier:
            return createExposedSession(session, context);
        }

    image

    2.1.2.1构建Session

    2.1.2.2设置session过期时间

    2.1.2.3onStart操作,作为session监听器点(本例无监听器

    2.1.2.4调用监听器onStart(本例无监听器

    2.1.2.5创建

    2.1.2.1继而AbstractNativeSessionManager.createSession()调用AbstractValidatingSessionManager.createSession() 启用session的验证功能,

    protected Session createSession(SessionContext context) throws AuthorizationException {
            enableSessionValidationIfNecessary();
            return doCreateSession(context);
        }

    继续调用DefaultSessionManager.doCreateSession(),DefaultSessionManager调用newSessionInstance,

    protected Session doCreateSession(SessionContext context) {
            Session s = newSessionInstance(context);
            if (log.isTraceEnabled()) {
                log.trace("Creating session for host {}", s.getHost());
            }
            create(s);
            return s;
        }

    获得SimpleSessionFactory工厂后构建调用SimpleSessionFactory.createSession()

    此时session中只有时间戳、session失效时间等信息

    dy1l5tow

    继而调用DefaultSessionManager.create() 持久化session(由于例子中未设置外部DAO则使用的是MemorySessionDAO实例

    protected void create(Session session) {
            if (log.isDebugEnabled()) {
                log.debug("Creating new EIS record for new session instance [" + session + "]");
            }
            sessionDAO.create(session);
        }

    这一步中会 为session生成一个UUID作为sessionID,并保存到session中,调用storeSession()将session 及其ID保存在MemorySessionDAO实例中的一个ConcurrentMap sessions中

    protected Serializable doCreate(Session session) {
            Serializable sessionId = generateSessionId(session);
            assignSessionId(session, sessionId);
            storeSession(sessionId, session);
            return sessionId;
        }

    最后成功返回session

    2.1.2.2依据全局session过期时间设置session并更新到sessionDAO

    protected void applyGlobalSessionTimeout(Session session) {
            session.setTimeout(getGlobalSessionTimeout());
            onChange(session);
        }

    hsmx3vg4

    2.1.2.5

    将SimpleSession转化为外部可用的DelegatingSession

    protected Session createExposedSession(Session session, SessionContext context) {
            return new DelegatingSession(this, new DefaultSessionKey(session.getId()));
        }

    2.1.3将session包装成统一的StoppingAwareProxiedSession,后续通过委托操作session内的方法

    protected Session decorate(Session session) {
            if (session == null) {
                throw new IllegalArgumentException("session cannot be null");
            }
            return new StoppingAwareProxiedSession(session, this);
        }

    vqn0nz1fruydqdo1

    最后各处返回得到session

    2.2在session中插入值

    session.setAttribute("someKey", "aValue");

    调用StoppingAwareProxiedSession父类方法ProxiedSession.setAttribute(),其中

    public void setAttribute(Object key, Object value) throws InvalidSessionException {
            delegate.setAttribute(key, value);
        }

    继而调用DelegatingSession.setAttribute(),其中调用并调用AbstractNativeSessionManager.setAttribute(),参数sessionKey为当前DelegatingSession的sessionKey

    public void setAttribute(SessionKey sessionKey, Object attributeKey, Object value) throws InvalidSessionException {
            if (value == null) {
                removeAttribute(sessionKey, attributeKey);
            } else {
                Session s = lookupRequiredSession(sessionKey);
                s.setAttribute(attributeKey, value);
                onChange(s);
            }
        }

    image

    2.2.1判断来值是否为空

    2.2.2.1

    lookupRequiredSession(sessionKey)经过一系列过程,获得sessionId,依据sessionId由sessionDAO从DAO中获取simplesession实例

    2.2.2.2空则删除对应的session参数

    2.2.3获得的session设置参数

    2.2.4sessionDAO中更新session

    2.2在session中查找值

    String value = (String) session.getAttribute("someKey");

    调用StoppingAwareProxiedSession父类方法ProxiedSession.getAttribute(),

    public Object getAttribute(Object key) throws InvalidSessionException {
            return delegate.getAttribute(key);
        }

    与setAttribute()类似,从DAO中依据由sessionKey得到的sessionID获得SimpleSession的实例,再调用其getAttribute方法获得参数

    public Object getAttribute(SessionKey sessionKey, Object attributeKey) throws InvalidSessionException {
            return lookupRequiredSession(sessionKey).getAttribute(attributeKey);
        }

    至此一个简单的Session获取及参数写入读取便完成了

    参考:

    http://shiro.apache.org/10-minute-tutorial.html

    http://shiro.apache.org/session-management.html

    http://www.apache.org/dyn/closer.cgi/shiro/1.3.2/shiro-root-1.3.2-source-release.zip

    转载请注明作者及来源:https://www.cnblogs.com/codflow/

  • 相关阅读:
    【算法学习笔记】76.DFS 回溯检测 SJTU OJ 1229 mine
    【算法学习笔记】75. 动态规划 棋盘型 期望计算 1390 畅畅的牙签盒(改)
    【算法学习笔记】74. 枚举 状态压缩 填充方案 SJTU OJ 1391 畅畅的牙签袋(改)
    【算法学习笔记】73.数学规律题 SJTU OJ 1058 小M的机器人
    【算法学习笔记】72.LCS 最大公公子序列 动态规划 SJTU OJ 1065 小M的生物实验1
    【算法学习笔记】71.动态规划 双重条件 SJTU OJ 1124 我把助教团的平均智商拉低了
    【算法学习笔记】70.回文序列 动态规划 SJTU OJ 1066 小M家的牛们
    【算法学习笔记】69. 枚举法 字典序处理 SJTU OJ 1047 The Clocks
    【算法学习笔记】68.枚举 SJTU OJ 1272 写数游戏
    【算法学习笔记】67.状态压缩 DP SJTU OJ 1383 畅畅的牙签袋
  • 原文地址:https://www.cnblogs.com/codflow/p/shiro_source_code_2.html
Copyright © 2011-2022 走看看