Java SecurityManager - how to ensure a method is run only by another method?
Java SecurityManager - how to ensure a method is run only by another method?
I want B to be run only by the private
method A#getSensitiveData()
that uses or does some processing on sensitive data (example: cryptographic keys, national id, whatever).
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.
Please take into account that the code would be obfuscated, so please refrain from putting in any package names as String
.
String
What must I write with SecurityManager#checkPrivilege()
and AccessController.doPrivileged()
before I can achieve such an effect?
SecurityManager#checkPrivilege()
AccessController.doPrivileged()
EDIT: Obviously this is different because the so called "answer" does not contain any CODE. WORKING CODE is worth infinitely more than "oh, just do this and that".
B.getSensitiveData
2 Answers
2
You could do something like this:
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;
And to call the method:
public final byte getSensitiveData(StackTraceElement e)
if (verify(e))
// Do something good
In your A
class call your B
class like this:
A
B
return sensitiveHolder.getSensitiveData(Thread.currentThread().getStackTrace());
I don't know if this is what you need or it is near that. You could play around the values in the equals
section of the if
. I got and modified the example from this site.
equals
if
If you're able to use JDK 9+, which introduces StackWalker
, this sort of thing might work for you. This technique seems to supersede use of sun.reflect.Reflection#getCallerClass(int)
. (I hope you weren't counting on a SecurityManager-related answer.)
StackWalker
sun.reflect.Reflection#getCallerClass(int)
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
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
For a working answer with code that solves the question of how
B.getSensitiveData
can check and limit who is calling it, see stackoverflow.com/a/41420960/14955 It does not use a SecurityManager, though.– Thilo
May 19 at 1:30