集成Shiro后当遇到404错误时会丢失session

yxlnum 2014-01-05

场景:

1、首先登录成功后访问正常页面没有问题的;

2、接着访问一个不存在的页面,即跳到相应的404页面,假设我的页面是jsp的;

3、再刷新一下就会又跳到登录页面。

场景分析:

1、首先登录成功,假设JSESSIONID=e688f231-c0f0-4757-b85b-9ff1e62221b3;

2、接着访问一个不存在的页面,提交的JSESSIONID=e688f231-c0f0-4757-b85b-9ff1e62221b3;即提交的JSESSIONID和登录成功的一样;没什么问题;

3、接着随便访问一个地址,会得到JSESSIONID=19eqzaptfpxad17y06dz3uc6xz;两次JSESSIONID不一样且格式不类似,【1、2】步骤的明显是Java UUID生成的key;而第二个则像是如Jetty容器生成的;

4、为什么呢?

技术分析:

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);
        }
        Cookie template = getSessionIdCookie(); //此处得到JSESSIONID的一个cookie模板
        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配置<dispatcher>ERROR</dispatcher>,然后在其filterChainDefinitions中添加/WEB-INF/jsp/error/error = anon;

相关推荐

LetonLIU / 0评论 2020-05-29