一尘不染

控制是否更新会话时间戳

tomcat

在与Tomcat 7.0上的Spring Web
MVC一起运行的应用程序中,我有某些控制器,尽管对它们的请求将需要身份验证和有效的会话,但我不希望更新该会话的到期时间戳。换句话说,我希望会话在没有发生此特定HTTP请求的情况下完全过期。

如果重要的话,这些是AJAX方法,尽管我不知道是否有用。

可以通过通用Java
EE或某些特殊的Tomcat挂钩完成此操作吗?还有另一种方法可以做到这一点吗?我知道http://download.oracle.com/javaee/6/api/javax/servlet/http/HttpSession.html#setMaxInactiveInterval%28int%29,但这似乎与我想要的相反。


阅读 249

收藏
2020-06-16

共1个答案

一尘不染

访问 时间
访问
会话时更新HttpServletRequest#getSession。因此,如果您确定不篡改该会话,则应该可以。
更新:
基于JavaDoc,上述说法是不正确的(即使您彻底搜索了源代码,也没有找到造成这种行为的任何代码)。

另一方面,如果您需要访问AJAX请求中的会话,那么您就很费力。我能想到的唯一解决方案是lastAccessTime手动存储(例如,在servlet过滤器中),然后检查会话超时并手动使会话无效(例如,在同一过滤器中)。那应该很简单并且易于实现。


更新: 仅出于乐趣,我实现了过滤器(未测试):

public class SessionInvalidationFilter implements Filter {

    private static final String LAST_ACCESS_SESSION_ATTR = "lastAccessTime";

    private static final long SESSION_TIMEOUT = 1000 * 60 * 20; // 20 minutes

    private static final String IGNORE_ACCESS_URI = "/this/will-not/update/access-time";

    @Override
    public void init(FilterConfig arg0) throws ServletException {
    }

    @Override
    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // Cast to HTTP request and response
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        // Check if we are handling standard request
        if (!IGNORE_ACCESS_URI.equals(httpRequest.getRequestURI())) {
            chain.doFilter(new SessionAccessAwareRequest(httpRequest), response);
            return;
        }
        // Now we can handle the special case of non-tracked request
        boolean expired = false;
        HttpSession session = httpRequest.getSession(false);
        if (session == null) {
            // No session means the AJAX contained no or incorrect JSESSIONID
            expired = true;
        } else {
            Long lastAccessTime = (Long) session.getAttribute(LAST_ACCESS_SESSION_ATTR);
            if (lastAccessTime == null || lastAccessTime + SESSION_TIMEOUT < System.currentTimeMillis()) {
                session.invalidate(); // Invalidate manually
                expired = true;
            }
        }
        // Handle error or process normally
        if (expired) {
            httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST);
        } else {
            chain.doFilter(request, response);
        }
    }

    private static class SessionAccessAwareRequest extends HttpServletRequestWrapper {

        public SessionAccessAwareRequest(HttpServletRequest request) {
            super(request);
        }

        @Override
        public HttpSession getSession() {
            return getSession(true);
        }

        @Override
        public HttpSession getSession(boolean create) {
            HttpSession session = super.getSession(create);
            if (session != null) {
                session.setAttribute(LAST_ACCESS_SESSION_ATTR, System.currentTimeMillis());
            }
            return session;
        }

    }

}
2020-06-16