会话超时时的ThreadLocal行为

时间:2013-07-09 04:30:19

标签: spring session spring-security thread-local-storage

我正在开发基于Java的Web应用程序,我们使用ThreadLocal来跟踪当前登录的用户。现在,通常它完全正常。但是,只要存在会话超时,并且系统尝试访问该变量(来自ThreadLocal数据),它就会给出随机值(某些其他登录用户的值)。理想情况下,它应该返回一个空值。我很困惑这里发生了什么。

1 个答案:

答案 0 :(得分:1)

线程是汇集的,因此您需要确保为每个请求清除ThreadLocal。如果你在Filter中执行此操作,它可能看起来像这样:

private static final ThreadLocal<String> CONTEXT = new ThreadLocal<String>();

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {

    try {
        CONTEXT.set(userName);
        chain.doFilter(req,res);
    } finally {
        CONTEXT.remove();
    }
}

否则会发生什么:

  • UserA登录并与ThreadA关联(UserA在上下文中)
  • UserB登录并与ThreadB关联(UserB在上下文中)
  • UserA的会话超时,不再拥有与其会话相关联的用户信息
  • UserA使用ThreadB,然后再次使用ThreadB,看起来UserB在上下文中)

这不仅是一个安全问题,而且还是内存泄漏。虽然每个用户填充的线程只有一个看起来很小,但它可以加起来。此外,如果放置在ThreadLocal中的对象是该类型属于war的ClassLoader的对象,则每次取消部署/部署应用程序时都会有一个大的PermGen leak泄漏整个战争内容而不重新启动应用程序服务器

@LaurentG是正确的,使用Spring Security的方法是使用SecurityContextHolder。您可以看到SecurityContextPersistenceFilter确保finally块中的SecurityContext gets cleared out