Java SecurityManager - 如何确保方法仅由另一个方法运行?

时间:2018-05-18 08:32:11

标签: java security

我希望B只能由private方法A#getSensitiveData()运行,该方法使用或对敏感数据进行一些处理(例如:加密密钥,国家ID,等等)。

public final class A{
    private transient final B sensitiveHolder; //set at Constructor
    public A(B sensitiveHolder){
        this.sensitiveHolder = sensitiveHolder;
    }
    private final byte[] getSensitiveData(){
        return sensitiveHolder.getSensitiveData();
    }
}

public final class B{
    private transient final byte[] sensitiveData;//encrypt and set at Constructor
    public final byte[] getSensitiveData(){
        //check if it is run by A#getSensitiveData(); if it is, decrypt by DEK and give plaintext.
    }
}

请注意代码会被混淆,因此请不要将任何包名称添加为String

在我取得这样的效果之前,我必须用SecurityManager#checkPrivilege()AccessController.doPrivileged()写什么?

编辑:显然这是不同的,因为所谓的"答案"不包含任何CODE。工作代码的价值远远超过"哦,只是这样做,而且#34;。

2 个答案:

答案 0 :(得分:5)

你可以这样做:

private boolean verify(final StackTraceElement e[]) {
    boolean doNext = false;
    for (final StackTraceElement s : e) {
        if (doNext && s.getClassName().equals("A") && s.getMethodName().equals("getSensitiveData"))
            return true;
        doNext = s.getMethodName().equals("getStackTrace");
    }
    return false;
}

并调用方法:

public final byte[] getSensitiveData(StackTraceElement e[]){
    if (verify(e)) {
        // Do something good
    }
}

A课程中,按照以下方式致电B班级:

return sensitiveHolder.getSensitiveData(Thread.currentThread().getStackTrace());

我不知道这是你需要的还是接近它。您可以在equals的{​​{1}}部分中播放这些值。我从this网站获得并修改了示例。

答案 1 :(得分:3)

如果你能够使用引入StackWalker的JDK 9+,这种事情可能适合你。这种技术似乎取代了sun.reflect.Reflection#getCallerClass(int)的使用。 (我希望你不是指望与SecurityManager相关的答案。)

package asdf;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.EnumSet;
import java.util.List;
import java.util.stream.Collectors;

public class Asdf {

  @Test
  public void what() {
    get();
  }

  void get() {
    StackWalker.StackFrame stackFrame =
        StackWalker.getInstance(EnumSet.of(StackWalker.Option.RETAIN_CLASS_REFERENCE))
            .walk(stream -> {
              List<StackWalker.StackFrame> stackFrames = stream.collect(Collectors.toList());
              return stackFrames.get(1);
            });
    Assertions.assertEquals(Asdf.class, stackFrame.getDeclaringClass());
    Assertions.assertEquals("what", stackFrame.getMethodName());
    Assertions.assertEquals(0, stackFrame.getMethodType().parameterCount());

    // now do caller-sensitive stuff
  }
}