前段时间上司忽然叫我帮忙解决老项目上的一个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接触得少,并无往这方面想,就是见识限制了本身的想象,望勤能补拙。