Shiro 框架之登录访问创建session 时的源码解析

web项目中业务代码入口创建session,自定义Filter 的实现类

1、业务代码入口:

public class CheckSessionFilter implements Filter {

    Logger logger = LoggerFactory.getLogger(CheckSessionFilter.class);
    

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException {
        try {
            XSSRequestWrapper requestWrapper = new XSSRequestWrapper((HttpServletRequest) servletRequest);
            //核心实现代码
            Object userToken = requestWrapper.getSession().getAttribute(Constants.CONST_CAS_USER_TOKEN);
            String token = null == userToken ? null : String.valueOf(userToken);

            MDC.put("logId", UuidUtil.getShortUuid() + ((StringUtil.isNotBlank(token) && SysUserUtil.getUser() != null) ? "U" + SysUserUtil.getUserId() : ""));
            
            filterChain.doFilter(requestWrapper, servletResponse);
        } catch (Exception e) {
            logger.error("PrintLogFilter.e:", e);
            servletResponse.setCharacterEncoding("utf-8");
            servletResponse.getWriter().write(JSON.toJSON(R.error()).toString());
        } finally {
            MDC.clear();
        }

    }

    @Override
    public void destroy() {
    //暂时空实现

    }


}

2、点击 requestWrapper.getSession() 进入:

public class HttpServletRequestWrapper extends ServletRequestWrapper implements
        HttpServletRequest
   @Override
    public HttpSession getSession() {
        return this._getHttpServletRequest().getSession();//点击进入
    }

3、进入

public class ShiroHttpServletRequest extends HttpServletRequestWrapper 
   public HttpSession getSession() {
        return getSession(true);
    }

进入:

public HttpSession getSession(boolean create) {

        HttpSession httpSession;

        if (isHttpSessions()) {
            httpSession = super.getSession(false);
            if (httpSession == null && create) {
                //Shiro 1.2: assert that creation is enabled (SHIRO-266):
                if (WebUtils._isSessionCreationEnabled(this)) {
                    httpSession = super.getSession(create);
                } else {
                    throw newNoSessionCreationException();
                }
            }
        } else {
            if (this.session == null) {

                //核心代码,点击进入
                boolean existing = getSubject().getSession(false) != null;

                Session shiroSession = getSubject().getSession(create);
                if (shiroSession != null) {
                    this.session = new ShiroHttpSession(shiroSession, this, this.servletContext);
                    if (!existing) {
                        setAttribute(REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
                    }
                }
            }
            httpSession = this.session;
        }

        return httpSession;
    }

4、进入

public class DelegatingSubject implements Subject 

显示:

进入if语句 

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;
    }

5、点击进入:

public abstract class SessionsSecurityManager extends AuthorizingSecurityManager
public Session start(SessionContext context) throws AuthorizationException {
        return this.sessionManager.start(context);//进入
    }

6、进入:

public abstract class AbstractNativeSessionManager extends AbstractSessionManager implements NativeSessionManager, EventBusAware
 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);
    }

7、进入

public abstract class AbstractValidatingSessionManager extends AbstractNativeSessionManager
        implements ValidatingSessionManager, Destroyable 
protected Session createSession(SessionContext context) throws AuthorizationException {
        enableSessionValidationIfNecessary();
        return doCreateSession(context);//点击进入
    }

8、进入

public class DefaultSessionManager extends AbstractValidatingSessionManager implements CacheManagerAware 
protected Session doCreateSession(SessionContext context) {
        Session s = newSessionInstance(context);
        if (log.isTraceEnabled()) {
            log.trace("Creating session for host {}", s.getHost());
        }
        create(s);//点击
        return s;
    }

继续:

 

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

 

9、点击

public abstract class CachingSessionDAO extends AbstractSessionDAO implements CacheManagerAware 
 public Serializable create(Session session) {
        Serializable sessionId = super.create(session);//点击
        cache(session, sessionId);
        return sessionId;
    }

10、进入父类

    
    public Serializable create(Session session) {
        Serializable sessionId = doCreate(session);//进入
        verifySessionId(sessionId);
        return sessionId;
    }

11、点击进入子类业务方法

// 创建session,并保存到数据库
    @Override
    protected Serializable doCreate(Session session) {
        Serializable sessionId = super.doCreate(session);
       
        redisTemplate.opsForValue().set(Contans.REDIS_SESSION_KEY + sessionId.toString(), session);
        return sessionId;
    }

12、创建后返回到

public abstract class AbstractNativeSessionManager extends AbstractSessionManager implements NativeSessionManager, EventBusAware 
public Session start(SessionContext context) {
        Session session = createSession(context);
        applyGlobalSessionTimeout(session);//更新session失效时间
        onStart(session, context);
        notifyStart(session);
        //Don't expose the EIS-tier Session object to the client-tier:
        return createExposedSession(session, context);
    }

进入

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

 

13、进入

public class DefaultSessionManager extends AbstractValidatingSessionManager implements CacheManagerAware
protected void onChange(Session session) {
        sessionDAO.update(session);//进入
    }

14、进入

public abstract class CachingSessionDAO extends AbstractSessionDAO implements CacheManagerAware 
public void update(Session session) throws UnknownSessionException {
        doUpdate(session);//进入业务方法
        if (session instanceof ValidatingSession) {
            if (((ValidatingSession) session).isValid()) {
                cache(session, session.getId());
            } else {
                uncache(session);
            }
        } else {
            cache(session, session.getId());
        }
    }

15、点击进入

// 更新session的最后一次访问时间
    @Override
    protected void doUpdate(Session session) {
        super.doUpdate(session);
        String key = Contans.REDIS_SESSION_KEY + session.getId().toString();
        redisTemplate.opsForValue().set(key, session);
        redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
    }

到此,这个业务Filter的实现类流程分析完毕,下一篇继续分析其他的过滤器,敬请期待!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寅灯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值