【问题标题】:ThreadLocal sharing data?ThreadLocal 共享数据?
【发布时间】:2013-01-22 14:46:03
【问题描述】:

无论如何,我知道以下是不可能的,但它发生在我们的一个生产环境中:

设置

  • ESAPI 2.01
  • 主 servlet 过滤器设置和删除当前请求线程本地对象:

    try {
        ESAPI.httpUtilities().setCurrentHTTP(request, response);
    
        // filter logic ...
    } catch (Exception e) {
        LOG.error(Logger.SECURITY_FAILURE, "Error in ESAPI "
                + "security filter: " + e.getMessage(), e);
        request.setAttribute("message", e.getMessage());
    } finally {
        ESAPI.clearCurrent();
    }
    

所有请求都通过这个过滤器,ESAPI.currentRequest() 在整个系统中使用。

  • 路径 A (http://server/path_a/)
    • 一直执行直到到达method_a,此方法无法从path_b 访问
  • 路径 B (http://server/path_b)
    • 直到到达method_b,无法从path_a访问

这两条路径都经过 servlet 过滤器(映射“/*”)

我收到的一封错误邮件表明path_a 正在引发错误,这反过来又会启动错误邮件,在邮件代码中,当前请求(通过ESAPI.currentRequest())被枚举为请求信息。

问题

在错误邮件中,来自path_a 的请求信息与来自method_b 的堆栈跟踪信息相关,对我来说这似乎是不可能的,因为两者都在不同的线程中运行。

问题

这怎么可能?我无法在本地重新创建它,除了设置和清除 ThreadLocal 之外,我还必须采取哪些预防措施?这可能是tomcat设置的问题吗?我迷路了。


PS:问题中的代码已被简化,因为示例代码库太大


【问题讨论】:

  • 过滤器我不熟悉,换个角度看,邮件是怎么组成的?过滤器是否为您执行此操作,或者可能有一些代码不是线程安全的?
  • 从单例对象调用错误邮件方法,方法中ESAPI.currentRequest()用于枚举信息

标签: java tomcat servlet-filters thread-local esapi


【解决方案1】:

阅读 ESAPI 代码https://code.google.com/p/owasp-esapi-java/source/browse/trunk/src/main/java/org/owasp/esapi/reference/DefaultHTTPUtilities.java 有一些关于线程本地的可疑做法。

我要说的最大问题是它使用InheritableThreadLocal。如果线程 A 派生了一个线程 B,B 将继承 A 的线程局部值;但是,当 A 然后清除本地线程时,它不会影响 B,因此 B 的继承值将保留。 ESAPI 可能不应该使用InheritableThreadLocal

如果不了解有关应用程序中线程的更多信息,我无法说出这会如何产生您看到的问题。

【讨论】:

  • 感谢您的回答,我检查了代码,电子邮件构建任务已提交给ExecutorService,所以它运行时使用了一个过时的请求?你能澄清一下工作原理吗?我应该使用 ESAPI 开票吗?
  • 任务可能被分派到从不同线程派生的现有线程,因此从该线程继承线程本地请求。在提交电子邮件任务之前,应在此线程上生成请求信息。而对于 ESAPI,我认为使用 InheritableThreadLocal 肯定是错误的。
猜你喜欢
  • 1970-01-01
  • 2011-08-22
  • 1970-01-01
  • 2012-12-11
  • 2013-09-01
  • 1970-01-01
  • 2022-01-10
  • 2021-05-05
  • 2011-02-10
相关资源
最近更新 更多