记一次与Shiro有关的错误,404导致session丢失需要重新登录

一 问题描述

前段时间上司突然叫我帮忙解决老项目上的一个bug,出现的问题是不同用户账号,进入同一个页面,有个别用户刷新一下当前页面就会重定向到登录页面,需要重新登录。

这是一个几年前的一个项目,使用的是Srping + Spring MVC + Shiro + Jsp的项目,之前没用过Shiro,所以对Shiro了解得不多。

二 问题排查

打开项目源码,先看进那个页面前时都做了什么处理。这是一个作品评审的页面,所以在返回页面前,分别把作品、评审规则、评委等数据put回了页面。

因为每个用户进入这个页面不同的是那个作品List,所以我优先判断是这里出问题,所以先注释掉,不把作品集合put回页面,注释掉后果然不会再出现重新刷新就会重定向到登录页面的问题。

接着我前往Jsp页面查看,发现也只是一个简单的for循环把作品集合输出,没毛病呀。

forEach items="${worksFileVoList}" var="worksFileVo" varStatus="s">
    
  • if test="${s.count == 1}">class="on" data-uuid="${worksFileVo.fileId}"if>>"javascript:void(0)" onclick="fileAction(this,'${worksFileVo.fileId}')">"${pageContext.request.contextPath}/res/suffix/${worksFileVo.extension}.jpg">

    "word">${worksFileVo.fileName}

  • forEach> 复制代码

    最后我想,该不会是这个图片的请求导致的吧,于是我又把img的src去掉,然后运行发现问题也不会出现了。

    我抱着好奇的心理,把代码恢复运行,然后打开F12查看Cookie,发现这位有问题的账号每次进入这个页面时,他的JSESSIONID就会被刷新,然后才导致需要重新登录。仔细观察了一下,这个账号,有个别作品的img是请求不到,是404,因为没这个图片,我补回了这张图片,问题就解决了,但这是个治标不治本的办法。

    为什么有个404请求,就导致要重新登录了呢,难受呀,百思不得其解。

    三 解决问题

    问题原因和解决方法在这位老哥的集成Shiro后当遇到404错误时会丢失session文章中写得很清楚了,这里我复述一下。

    1 首先如果登录成功,Shiro的DefaultWebSessionManager会默认通过如下方式添加JSESSIONID Cookie到响应:

    private void storeSessionId(Serializable currentId, HttpServletRequest request, HttpServletResponse response) {
        if (currentId == null) {
            String msg = "sessionId cannot be null when persisting for subsequent requests.";
            throw new IllegalArgumentException(msg);
        } else {
            Cookie template = this.getSessionIdCookie();
            Cookie cookie = new SimpleCookie(template);
            String idString = currentId.toString();
            cookie.setValue(idString);
            cookie.saveTo(request, response);
            log.trace("Set session ID cookie for session with id {}", idString);
        }
    }
    复制代码

    2 如果客户端访问时会带着个Cookie回来;但是注意:容器不认识的(Web容器并没有真正创建HttpSession);Shiro默认情况下会生成自己的一套Session,默认是MemorySessionDAO;即放到内存中的;和Web容器没有任何关系;

    3 接着访问一个错误的页面(如jsp);此时到了Shiro过滤器,过滤器通过;然后最后forward到这个错误页面;大家应该知道默认情况下jsp页面是需要session的;所以此时jsp会调用request.getSession(),此时创建了一个Session;这会往Cookie写JSESSIONID的。

    解决方法:

    1、换一个新的session key,如uid; 推荐这种做法;

    2、错误页面 设置<%@ page session="false' %>;

    3、给shiro filter配置ERROR,然后在其filterChainDefinitions中添加/WEB-INF/jsp/error/error = anon;

    我这里使用第一种方法解决问题

    "sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        
        
        "sessionIdCookieEnabled" value="true"/>
        "sessionIdCookie" ref="sessionIdCookie"/>
    
    
    
    "sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        "name" value="new.session.id"/>
    
    复制代码

    四 总结

    本次排错,虽然很快就找到了问题所在,但是最终在思考原因时,因为对Shiro接触得少,并没有往这方面想,就是见识限制了自己的想象,望勤能补拙。

    你可能感兴趣的:(记一次与Shiro有关的错误,404导致session丢失需要重新登录)