我希望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()
写什么?
答案 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
}
}