【问题标题】:Java SecurityManager - how to ensure a method is run only by another method?Java SecurityManager - 如何确保一个方法只能由另一个方法运行?
【发布时间】:2018-10-28 15:25:22
【问题描述】:

我希望 B 仅由 private 方法 A#getSensitiveData() 运行,该方法使用或对敏感数据进行一些处理(例如:加密密钥、国民身份证等)。

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()写什么才能达到这样的效果?

编辑:显然这是不同的,因为所谓的“答案”不包含任何代码。 WORKING CODE 比“哦,做这个做那个”更有价值。

【问题讨论】:

  • 对于解决B.getSensitiveData如何检查和限制谁在调用它的问题的代码的工作答案,请参阅stackoverflow.com/a/41420960/14955它不使用SecurityManager。

标签: java security


【解决方案1】:

你可以这样做:

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());

我不知道这是您需要的还是附近的。您可以使用ifequals 部分中的值。我从this 站点获取并修改了示例。

【讨论】:

    【解决方案2】:

    如果您能够使用引入 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
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-08
      • 2012-08-21
      相关资源
      最近更新 更多