系统抛404错误,导致session失效?

2019-03-15  本文已影响0人  Hogantry

1、问题背景

最近项目开发过程中遇到一个比较奇怪的问题,每次成功登录系统之后,只要一进入某个JSP页面,就会出现session失效,需要重新登录的情况。问题比较奇葩,通过细致查看,发现在该JSP页面中引入了一个不存在的js脚本文件,删除这段JS引用之后,问题修复了,对于问题的起因也就没再继续关注。然而,一次偶然的操作,session失效的问题再次发生,操作流程是登录系统后,由于系统尚在开发过程中,访问了一个还未开发的URL,跳转到系统配置的404页面,此时session失效了。起初由于惯性思维,简单的认为,肯定是404页面中引入了不存在JS或CSS文件,查看之后发现并不存在该问题,由此引发了session失效问题的原理思考。

2、解决思路

根据问题背景的描述,session失效的问题,并不简简单单是引错JS/CSS文件引起的。而通过比较前后两次问题出现的情况,我们发现他们唯一的共同点就是系统抛出了404错误(引入不存在的JS/CSS文件,也会抛404错误)。
再来看下系统session的实现方式。系统做了集群,所以用redis做了分布式session,使用了spring-session-data-redis框架。我们知道,使用spring-session-data-redis框架是需要在web.xml中配置filter的,且是拦截所有请求。spring session的底层原理就是在拦截到请求后,重新包装request和response对象,此时系统中再通过request.getSession()方法获取session,就会使用包装后的request对象,去redis中创建和获取session。具体的实现原理就不过多介绍,可自行百度。我们看下web.xml中的具体配置

<error-page>
    <error-code>404</error-code>
    <location>/WEB-INF/views/common/404.jsp</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/WEB-INF/views/common/500.jsp</location>
</error-page>
<filter>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

这里注意filter-mapping的配置,filter-mapping标签下有<dispatcher>子标签,他指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。
<dispatcher> 子元素可以设置的值及其意义:

用户可以设置多个<dispatcher> 子元素用来指定 Filter 对资源的多种调用方式进行拦截。我们这里没有配置,也就是使用的默认的REQUEST方式,此时如果系统中有任何调用response.sendError(int error_status_code) 方法时,系统都会通过ERROR的方式去调用相应的servlet。这样的流程是不会被我们配置的filter所拦截的,那此时再去获取session就不会从redis获取,session失效也就是必然了。
问题原理找到了,那修复也就简单了,直接在filter-mapping中增加dispatcher子标签,由于我们是希望使用spring session来全盘管理系统的session,所以这里建议是将所有的dispatch类型都配置上,确保任何方式的请求都会被该filter拦截。

<filter-mapping>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>
上一篇下一篇

猜你喜欢

热点阅读