在Java的私有静态字段中保存敏感数据是否安全?

问题描述 投票:0回答:1

我最近偶然发现了一些无法以我惯用的方式传递数据的问题。

假设我们创建了一个提供程序类,该提供程序类由另一个我们无法修改的使用者类实例化并调用。提供者为消费者提供了一些需要敏感数据的对象实例。显然,将这​​些数据硬编码到我们的提供程序类中是一种不好的做法。在我的情况下,此敏感数据是在运行时生成的,无法进行硬编码。

我的想法是为该提供程序类提供一个私有静态字段,该字段的设置器,而没有getter。现在,即使创建了该提供程序类的实例,我们也无法访问该私有静态字段,只有提供程序类本身才能读取它。


让我们提供一些代码。假设我们具有以下Consumer类和Provider接口:

消费者

public class Consumer {

    private final Class<? extends ProviderInterface> clazz;

    public Consumer(Class<? extends ProviderInterface> clazz) {
        this.clazz = clazz;
    }

    public void providerToSystemOut() throws IllegalAccessException, InstantiationException {
        System.out.println(clazz.newInstance().call().toString());
    }

}

ProviderInterface

public interface ProviderInterface {

    public Object call();

}

消费者仅接受消费者的类别作为参数。因此,我们不能自己创建该类来提供敏感数据。

为了传递敏感数据,我们创建了以下提供者和主要名称:

提供者

public class Provider implements ProviderInterface {

    private static Object data = null;

    public static void setData(Object data) {
        Provider.data = data;
    }

    public Object call() {
        String str;
        if (data != null && (str = data.toString()).length() > 3) {
            Object object = "successfully received/processed sensitive data: "
                    + str.substring(0, 3)
                    + str.substring(3).replaceAll(".", "*");
            data = null;
            return object;
        } else {
            data = null;
            return "not enough data provided";
        }
    }
}

Main

public class Main {

    public static void main(String[] args) {

        Provider.setData("sensitive data");

        try {
            new Consumer(Provider.class).providerToSystemOut();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

我的问题

此代码可以正常工作,而且似乎很安全。但我想确定这是否是解决此问题的最佳方法。我采用的是一种好的做法吗?安全吗?有没有一种简单的方法可以使某人获取敏感数据?如果这不是最好的方法,那会更好吗?

某些背景

我在处理硒化物时遇到了这个问题。通常,selenide会自己创建其WebDriver实例。要为其提供自定义WebDriver,需要Provider类。然后Selenide具有该提供程序的类名的系统属性,并使用此String创建自定义提供程序的实例,并使用WebDriver调用向selenide提供的方法。

java security static field private
1个回答
0
投票

实际上,从静态字段访问数据更容易通过反射获得,但实际上,它是静态还是私有无关紧要。

但是您实际上只需要担心存储的数据是否可用于客户端...

即,您出于任何原因将jar文件分发给其他人/客户。

如果是这种情况,那么就没有真正的方法来阻止某人访问数据。

如果您有权访问jar文件,则可以执行以下类似操作,以对代码进行任何操作。

public static void agentmain(String agentArgs, Instrumentation inst) {
    Class[] allYourClassesAtRuntime = inst.getAllLoadedClasses();
    for (Class yourClass : allYourClassesAtRuntime) {
        try {
            if (yourClass.getSimpleName().equals("Provider")) {
                Field yourClassField = yourClass.getField("data");
                yourClassField.setAccessible(true); //destroys private
                Object yourData = yourClassField.get(null);
                System.out.println("Got your data: " + yourData);
                //can do as you wish from here
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

当代理附加到JVM时,将调用上述方法。

TL / DR:客户端数据永远都不安全,因此您应将希望保护的所有内容保存在服务器端,并在两者之间进行协商。如果在某些情况下您必须在客户端上拥有一些敏感数据,那么不要将您不希望看到的任何对象保留在构造函数或方法之外。保持它们在本地。构造函数也比方法更难反编译。

© www.soinside.com 2019 - 2024. All rights reserved.