簡體   English   中英

Java - 我怎樣才能完全清除變量

[英]Java - How can I completely clear a variable

我有一個 Spring 引導應用程序,它使用 CredentialsService class 將憑據存儲為 GuardedStrings 並在其他類請求時返回它們。

問題出現的地方在於我們使用 Checkmarx 來掃描我們的代碼並發現潛在問題。 在用戶名/密碼的存儲不再是問題的情況下,我仍然必須使用字符串變量來返回純文本憑據。 Checkmarx 不喜歡這樣——尤其是對於密碼。

這是 CredentialsService 的縮寫視圖:

@Component
public class CredentialsService {
    
    final ExecutorService executor = Executors.newSingleThreadExecutor();

    private GuardedString customerApiPassword;
    . . . 
    private StringBuilder clearCustomerApiPassword;

    public CredentialsService( . . .
            @Value("${customerapi.pwd}") String customerApiPassword,. . .) {
        
        setCustomerApiPassword(customerApiPassword);
        . . .
    }

    private void setCustomerApiPassword(String customerApiPasswordString) {
        this.customerApiPassword = new GuardedString(customerApiPasswordString.toCharArray());
        this.customerApiPassword.makeReadOnly();        
    }
    
    public String getCustomerApiPasswordNo() {
        
        clearCustomerApiPassword = new StringBuilder();
        customerApiPassword.access(new GuardedString.Accessor() {
            @Override
            public void access(final char[] clearChars) {
                clearCustomerApiPassword.append(clearChars);
            }
        });
        customerApiPassword.dispose();
        System.out.println("DGC: clearCustomerApiPassword is " + clearCustomerApiPassword);
        Runnable clearFromMemory = () -> {
            clearCustomerApiPassword = null;
            System.out.println("DGC: clearCustomerApiPassword is " + clearCustomerApiPassword);
        };
        executor.execute(clearFromMemory);
        return clearCustomerApiPassword.toString();
    }

然后請求者訪問它需要的值:

    IntegrationApiUtil.setBasicAuthKey(headers, credentialsService.getCustomerApiUsername(), credentialsService.getCustomerApiPassword());

然而 Checkmarx 仍然不高興。 我使用相同的方法來存儲 GuardedString 用戶名和密碼,並使用完全相同的方法來清除返回的字符串。 Checkmarx 對用戶名很好,但它仍然抱怨密碼:

    Method clearCustomerApiPassword; at line 24 of
src/main/java/com/.../service/CredentialsService.java
defines clearCustomerApiPassword, which is designated to contain user passwords. However, while plaintext
passwords are later assigned to clearCustomerApiPassword, this variable is never cleared from memory.

我已經嘗試了各種各樣的方法——在服務最后一次使用后銷毀服務的 finalize 方法,將所有變量顯式設置為 null 並調用垃圾收集器的 disposeAll 方法。 使用上面的代碼,我在每個 get 方法中創建一個單獨的線程來將“清除”變量設置為 null,因為我將值返回給請求者。 雖然我可以確認這種最新方法確實為請求者提供了正確的值,並將變量設置為 null,但似乎沒有什么能滿足 Checkmarx 的要求。

有沒有人有任何想法?

提前致謝。

D

一旦將敏感數據放入像String這樣的不可變 object 中,數據將在 memory 中保留很長時間。 您可以釋放變量,但即使沒有物理參考,該值仍將位於 memory 中。 你可以運行 GC,它仍然會存在。 唯一有幫助的是使用相同的 memory 空間創建另一個變量並覆蓋該值。

長話短說:只要你把密碼放在String中,Checkmarx 就會抱怨。

你有兩件事可以做:

  • 您要么僅依賴char[]並在使用后清除數組,
  • 或者如果您被迫為您的案例請求特殊例外,請使用String值。

好吧,通過將密碼作為常規String返回/傳輸,您有點丟掉了在GuardedString中存儲密碼的所有價值。

對Checkmarx了解不多,但它只是一個掃碼工具,所以很容易上當。 我建議實際解決問題,而不是試圖將它們掃到地毯下。

  1. 請注意GuardedString構造函數接受char[] ,而不是String 這是第一個問題——你應該將你的密碼從源代碼作為char[]攜帶到這一點—— 這里有更多關於它的信息。
  2. 不要將String返回給您的消費者 - 返回GuardedString或至少一個char[]
  3. 取決於您使用此類/庫的目標消費者,但嘗試為他們提供一種在盡可能短的時間內訪問實際密碼的方法,並在使用后清除char[] (以消費者不會擁有的方式)自己做,因為他可以忘記)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM