记一次与Shiro有关的错误,404致使session丢失须要从新登陆

一 问题描述

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

这是一个几年前的一个项目,使用的是Srping + Spring MVC + Shiro + Jsp的项目,以前没用过Shiro,因此对Shiro了解得很少。java

二 问题排查

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

由于每一个用户进入这个页面不一样的是那个做品List,因此我优先判断是这里出问题,因此先注释掉,不把做品集合put回页面,注释掉后果真不会再出现从新刷新就会重定向到登陆页面的问题。apache

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

<c:forEach items="${worksFileVoList}" var="worksFileVo" varStatus="s">
    <li <c:if test="${s.count == 1}">class="on" data-uuid="${worksFileVo.fileId}"</c:if>><a href="javascript:void(0)" onclick="fileAction(this,'${worksFileVo.fileId}')"><img src="${pageContext.request.contextPath}/res/suffix/${worksFileVo.extension}.jpg"></a>
        <p class="word">${worksFileVo.fileName}</p></li>
</c:forEach>
复制代码

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

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

为何有个404请求,就致使要从新登陆了呢,难受呀,百思不得其解。jsp

三 解决问题

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

1 首先若是登陆成功,Shiro的DefaultWebSessionManager会默认经过以下方式添加JSESSIONID Cookie到响应:this

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的。

解决方法:

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

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

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

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

<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    
    <!-- 额外添加多的配置 -->
    <property name="sessionIdCookieEnabled" value="true"/>
    <property name="sessionIdCookie" ref="sessionIdCookie"/>
</bean>

<!-- 指定本系统SESSIONID, 默认为: JSESSIONID 问题: 与SERVLET容器名冲突, 如JETTY, TOMCAT 等默认JSESSIONID,
        当跳出SHIRO SERVLET时如ERROR-PAGE容器会为JSESSIONID从新分配值致使登陆会话丢失! -->
<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
    <constructor-arg name="name" value="new.session.id"/>
</bean>
复制代码

四 总结

本次排错,虽然很快就找到了问题所在,可是最终在思考缘由时,由于对Shiro接触得少,并无往这方面想,就是见识限制了本身的想象,望勤能补拙。

相关文章
相关标签/搜索