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/

  • 相关阅读:
    Windows Server环境下消息队列之ActiveMQ实战
    Javascript 面向对象编程(一):封装
    Python常用函数
    redis源码(一):为redis添加自己的列表类型
    导出数据到Excel表格
    Oracle————存储过程与函数
    Solr搜索引擎 — 通过mysql配置数据源
    redis的安装和使用【2】redis的java操作
    MySql(四)Select条件查询
    MySql (二)入门语句和基本操作
  • 原文地址:https://www.cnblogs.com/codflow/p/shiro_source_code_2.html
Copyright © 2011-2022 走看看