2013-02-07 107 views
1

通過我知道下面的一切手段是不可能的,但它在我們的生產環境中的其中之一發生:ThreadLocal共享數據?

SETUP

  • 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:從所述問題代碼已經被簡化爲代碼庫是大爲例


error mail

+0

我對過濾器並不熟悉,但從另一個角度來看它,電子郵件是如何組成的?過濾器是否爲你做這件事,或者可能會有一些代碼不是線程安全的? – Jeroen

+0

錯誤郵件方法是從一個單例對象中調用的,在該方法中,'ESAPI.currentRequest()'用於枚舉信息 – epoch

回答

2

讀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

我不能說這可能會導致你看到的問題,而無需知道更多關於你的應用中的線程。

+1

感謝您的回答,我檢查了代碼,並將電子郵件構建任務提交給' ExecutorService',所以當它運行它使用過時的請求?你能澄清一下工作嗎?我應該用ESAPI打開一張票嗎? – epoch

+1

該任務可能被分派到由不同線程產生的現有線程,因此繼承該線程的線程本地請求。在提交電子郵件任務之前,請在此線程上生成請求信息。對於ESAPI,我認爲使用InheritableThreadLocal確實是一個錯誤。 – irreputable