Tomcat会话超时后登录报408,如何保持登录页面会话存活?
问题描述
现有一个Angular登录表单(FormControl),代码如下:
<form name="login" method ="POST" role="form" action="j_security_check"> <div class="login"> <label> Username</label> <input formControlName="username" name="j_username" autofocus required> </div> <div class="login"> <label> Password</label> <input type="password" formControlName="password" name="j_password" required> </div> <button class="submit" type="submit"> Sing In</button> </form>
登出方法通过POST请求使会话失效并刷新页面:
protected logoutUser() { this.http.post('/foo/logout', {}).subscribe ({ next: () => { location.reload(); //reloads the page after the post call invalidates the session }}); }
Tomcat配置了30分钟会话超时,出现以下问题:
- 登录页面闲置30分钟后,再次登录时
j_security_check的POST请求返回408超时错误 - 每次登录/登出SessionID都会变化
- 当前只能通过清除缓存解决该问题,尝试
location.reload(true)无效
解决方案
1. 登出时彻底清除会话Cookie
Tomcat的会话默认通过JSESSIONID Cookie维护,登出时仅使服务器端会话失效,但浏览器可能仍保留旧的JSESSIONID Cookie,超时后该Cookie已失效,导致登录请求携带无效Cookie触发408。修改登出方法,在跳转前清除该Cookie:
protected logoutUser() { this.http.post('/foo/logout', {}).subscribe ({ next: () => { // 清除JSESSIONID Cookie,覆盖原有失效Cookie document.cookie = "JSESSIONID=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure; HttpOnly"; // 直接跳转到登录页,避免加载缓存的旧会话信息 location.href = '/login'; }}); }
2. 给登录页面添加禁止缓存的响应头
浏览器可能缓存了登录页面的旧会话相关资源,需通过HTTP响应头强制禁止缓存。可通过Tomcat过滤器或后端控制器实现:
方式1:Tomcat过滤器配置
在web.xml中添加过滤器:
<filter> <filter-name>NoLoginCacheFilter</filter-name> <filter-class>com.yourpackage.NoLoginCacheFilter</filter-class> </filter> <filter-mapping> <filter-name>NoLoginCacheFilter</filter-name> <url-pattern>/login</url-pattern> <!-- 匹配你的登录页面路径 --> </filter-mapping>
过滤器实现代码:
public class NoLoginCacheFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResp = (HttpServletResponse) response; // 设置禁止缓存的响应头 httpResp.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); httpResp.setHeader("Pragma", "no-cache"); httpResp.setDateHeader("Expires", 0); chain.doFilter(request, response); } }
方式2:后端控制器直接设置
如果是Spring Boot等后端框架,可在登录页面的控制器方法中添加:
@GetMapping("/login") public String loginPage(HttpServletResponse response) { response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); response.setHeader("Pragma", "no-cache"); response.setDateHeader("Expires", 0); return "login"; }
3. 登录前主动获取新会话
在提交登录表单前,先发送一个GET请求到服务器(比如访问首页或空端点),获取新的有效JSESSIONID,再提交登录请求。修改Angular组件代码:
onLoginSubmit() { // 先发送GET请求获取新的有效会话 this.http.get('/').subscribe(() => { // 手动提交登录表单 document.forms['login'].submit(); }); }
同时修改登录按钮的点击事件,替换默认提交行为:
<button class="submit" type="button" (click)="onLoginSubmit()"> Sing In</button>
4. 调整会话超时配置(可选)
如果业务允许,可适当延长会话超时时间,但这只是缓解手段。在Tomcat的conf/web.xml中修改:
<session-config> <session-timeout>60</session-timeout> <!-- 改为60分钟,根据需求调整 --> </session-config>
内容的提问来源于stack exchange,提问作者user3822558
相关产品推荐
相关产品推荐

