简体   繁体   English

Java - 我怎样才能完全清除变量

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

I have a Spring Boot application that uses a CredentialsService class to store credentials as GuardedStrings and return them when requested by other classes.我有一个 Spring 引导应用程序,它使用 CredentialsService class 将凭据存储为 GuardedStrings 并在其他类请求时返回它们。

Where the problem arises is in the fact that we use Checkmarx to scan our code and catch potential issues.问题出现的地方在于我们使用 Checkmarx 来扫描我们的代码并发现潜在问题。 Where storage of the usernames/passwords are not a problem anymore, I still have to use a String variable to return the plain text credentials.在用户名/密码的存储不再是问题的情况下,我仍然必须使用字符串变量来返回纯文本凭据。 Checkmarx doesn't like that - especially for passwords. Checkmarx 不喜欢这样——尤其是对于密码。

This is the abbreviated view of the CredentialsService:这是 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();
    }

And then a requester accesses the values it needs with:然后请求者访问它需要的值:

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

However Checkmarx is still not happy.然而 Checkmarx 仍然不高兴。 I use the same approach for storing the GuardedString usernames and passwords and the exact same approach to clearing the Strings that are returned.我使用相同的方法来存储 GuardedString 用户名和密码,并使用完全相同的方法来清除返回的字符串。 Checkmarx is fine with the usernames, but it still complains about the passwords: 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.

I have tried all sorts of things - a finalize method to destroy the service after it is last used, a disposeAll method to explicitly set all variables to null and call the garbage collector.我已经尝试了各种各样的方法——在服务最后一次使用后销毁服务的 finalize 方法,将所有变量显式设置为 null 并调用垃圾收集器的 disposeAll 方法。 With the code above I am creating a separate thread in each get method to set the 'clear' variables to null as I return the value to the requester.使用上面的代码,我在每个 get 方法中创建一个单独的线程来将“清除”变量设置为 null,因为我将值返回给请求者。 While I can confirm that this latest approach does provide the requester with the correct values and also sets the variables to null, nothing seems to satisfy Checkmarx.虽然我可以确认这种最新方法确实为请求者提供了正确的值,并将变量设置为 null,但似乎没有什么能满足 Checkmarx 的要求。

Does anyone have any ideas?有没有人有任何想法?

Thanks in advance.提前致谢。

D D

Once you put sensitive data into an immutable object like String , the data will remain in the memory for a long time.一旦将敏感数据放入像String这样的不可变 object 中,数据将在 memory 中保留很长时间。 You can release the variable, but even without a physical reference the value will still sit in the memory.您可以释放变量,但即使没有物理参考,该值仍将位于 memory 中。 You can run GC, it will still be there.你可以运行 GC,它仍然会存在。 The only thing that would help would be a creation of another variable using the same memory space and overriding the value.唯一有帮助的是使用相同的 memory 空间创建另一个变量并覆盖该值。

Long story short: As long as you put your password in a String , Checkmarx will complain.长话短说:只要你把密码放在String中,Checkmarx 就会抱怨。

You have two things you can do:你有两件事可以做:

  • you either rely on char[] only and clear the array once used,您要么仅依赖char[]并在使用后清除数组,
  • or use a String value if you are forced to and request a special exception for your case.或者如果您被迫为您的案例请求特殊例外,请使用String值。

Well, you are kinda throwing away all the value of storing passwords in GuardedString by returning/transporting them as regular String .好吧,通过将密码作为常规String返回/传输,您有点丢掉了在GuardedString中存储密码的所有价值。

Don't know a lot about Checkmarx, but it's just a code scanning tool, so it's easy to fool.对Checkmarx了解不多,但它只是一个扫码工具,所以很容易上当。 I suggest actually fixing the problems, instead of trying to sweep them under the rug.我建议实际解决问题,而不是试图将它们扫到地毯下。

  1. Notice that GuardedString constructor accepts char[] , not a String .请注意GuardedString构造函数接受char[] ,而不是String That's the first problem - you should carry your password from the source up to this point as a char[] - more about it here.这是第一个问题——你应该将你的密码从源代码作为char[]携带到这一点—— 这里有更多关于它的信息。
  2. Don't return String to your consumer - return the GuardedString or at least a char[] .不要将String返回给您的消费者 - 返回GuardedString或至少一个char[]
  3. Depends on what consumers you are targeting with this class/library, but try to provide a way for them to access the actual passwords for as short time as possible, and clearning the char[] after usage (in a way that consumer will not have to do that himself, since he can forget)取决于您使用此类/库的目标消费者,但尝试为他们提供一种在尽可能短的时间内访问实际密码的方法,并在使用后清除char[] (以消费者不会拥有的方式)自己做,因为他可以忘记)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM