控制是否更新会话时间戳 [英] Control whether session timestamp is updated

查看:102
本文介绍了控制是否更新会话时间戳的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的Tomcat 7.0上使用Spring Web MVC运行的应用程序中,我有一些控制器,尽管对它们的请求需要身份验证和有效会话,但我不希望更新会话的到期时间戳。换句话说,我希望会话准确到期,否则会发生这个特定的HTTP请求。

In my application, which runs with Spring Web MVC on Tomcat 7.0, I have certain controllers where, although requests to them will require authentication and a valid session, I don't want the session's expiration timestamp to be updated. In other words, I want the session to expire exactly when it would have had this particular HTTP request not happened.

如果重要的话,这些是AJAX方法,尽管我不喜欢知道它是否确实。

These are AJAX methods if it matters, though I don't know if it does.

可以通过通用Java EE或一些特殊的Tomcat挂钩来完成吗?有没有其他方法来实现这一目标?我知道 http:// download.oracle.com/javaee/6/api/javax/servlet/http/HttpSession.html#setMaxInactiveInterval%28int%29 但这似乎与我想要的完全相反。

Can this be done through either generic Java EE or some special Tomcat hooks? Is there another way to achieve this? I know about http://download.oracle.com/javaee/6/api/javax/servlet/http/HttpSession.html#setMaxInactiveInterval%28int%29 but that seems like almost the opposite of what I want.

推荐答案

访问时间更新会话 访问的HttpServletRequest#的getSession 。因此,如果您确定没有篡改会话,那么您应该没问题。 更新:基于 JavaDoc 以上是不正确的(即使你彻底搜索了源代码,也没有发现任何负责此类行为的一段代码。)

Access time is updated only when the session is being accessed by HttpServletRequest#getSession. So if you make sure you are not tampering with the session, you should be OK. UPDATE: based on the JavaDoc the above is not true (even thou I searched the source code thoroughly and didn't find any piece of code responsible for such behavior).

另一方面,如果你需要在AJAX请求中访问会话,那你几乎搞砸了。我能想到的唯一解决方案是手动存储 lastAccessTime (例如在servlet过滤器中),然后检查会话超时和手动使会话无效(例如在同一过滤器中)。这应该非常简单易行。

On the other hand, if you need to access the session in your AJAX request, you are pretty much screwed. The only solution I can think of is to store lastAccessTime manually (e.g. in servlet filter) and then check session timeout and invalidate the session manually (e.g. in the same filter). That should be pretty straightforward and easy to implement.

更新:为了好玩我已实现过滤器(未测试):

UPDATE: Just for the fun I've implemented the filter (not tested):

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;
        }

    }

}

这篇关于控制是否更新会话时间戳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆