我正在寻找一个经过严格调用JavaScript的签名Applet。显然,源自JavaScript的线程比使用Java直接启动的任何线程更加沙箱化。例如,如果JavaScript线程调用Applet并记录导致日志文件滚动的内容,则会引发安全性异常。直接在Applet中启动的任何线程都不会遇到此安全性异常。 log4j的解决方案是使用异步appender。
但是对于其他安全性异常(例如在签名的Applet中使用Apache Axis但在JavaScript线程中),没有明显的方法来拥有一些异步线程。假设我有以下代码,如果从Java线程调用将起作用,并且如果通过JavaScript调用将失败并出现SecurityException:
public void someMethodCalledFromJavaScript() {
// Stuff that would throw a SecurityException
}
我看到以下三个选项,但它们可能并非全部有效。为了便于讨论,请忽略执行是同步还是异步,因为这很容易管理。我很难理解安全模型的细节。以下是我的三个可能选择:
开始一个新线程(这个会工作吗?):
public void someMethodCalledFromJavaScript() {
new Thread(new Runnable() {
public void run() {
// Stuff that would throw a SecurityException
}
}).start();
}
让Applet随时准备好通过JavaScript原始线程(此处高度简化的代码)触发的线程:
private volatile boolean doit = false;
// This code is running in a Thread, started @ Applet init time
public void alwaysWaiting() {
while (true) {
if (doit) {
doit = false;
// Stuff that would throw a SecurityException
}
}
}
public void someMethodCalledFromJavaScript() {
doit = true;
}
使用AccessController.doPrivileged:
public void someMethodCalledFromJavaScript() {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
// Stuff that would throw a SecurityException
return null;
}
});
}
根据我读到的AccessController.doPrivileged
,您使用当前安全权限的交集和您正在调用的代码的安全域的权限运行。这对我来说没有意义,好像你正在运行低安全域和高安全域的交集,你只会拥有低安全性域。很明显我不理解。
我看到的具体SecurityException
就是这个:
java.security.AccessControlException: access denied (java.lang.RuntimePermission accessDeclaredMembers)
但当然我对JavaScript调用签名Applet的上下文中的一般情况感到好奇,以及我如何允许一个源自JavaScript的线程与签名Applet的priv一起运行,就好像它是一个线程一样纯粹源自Applet。
上面哪些选择甚至可以起作用,哪些选择比其他选择更好,以及为什么。
答案 0 :(得分:11)
由于下面提到的原因而无法工作
当然会工作,但这比调用doPrivileged
更痛苦,但在语义上却有同样的效果。
是的,这将有效。
每个访问控制检查检查当前线程堆栈上的所有堆栈帧的集合(包括导致当前线程实例化的堆栈帧,递归)。如果有doPrivileged
帧,那么导致该帧的帧不会包含在该帧中(但实际的doPrivileged
帧包含)。
如果正在检查的权限不在该集合的每一帧中,则检查失败。
换句话说,线程的当前权限是此集合中的权限的交集。
因此,例如,如果特权代码doPrivileged
是一些试图打开文件的无特权代码,则检查将失败。同样,如果无特权代码doPrivileged
打开文件的特权代码,则检查将失败。但是,如果非特权代码调用特权代码并且特权代码依次调用doPrivileged
来打开文件,则检查将成功。
理论上,你应该只能授予你的Java代码库所需的权限(可能访问某个独立的目录),然后授予相同的权限将使用此特权代码的JavaScript代码,但我怀疑任何浏览器都有这样的功能。我很惊讶JavaScript甚至运行在另一个保护域而不是Java。
我从来没有完成过JavaScript< - > Java互操作,但似乎无论你需要使用JavaScript调用的方法都使用doPrivileged
块整个主体。
编辑:正如萨米所说,在特权代码中调用doPrivileged
块时,要小心 (并阅读他的回答)。
答案 1 :(得分:10)
我会选择doPrivileged。请注意,每个有权访问您的applet的人都可以下载并将其放在他们的网站上,并让他们自己的恶意javascript以您无法想象的方式调用它。
其他解决方案的安全含义几乎相同(编辑:尽管创建一个新的Thread不起作用,如Longpoke指出的那样),但它们更复杂。所以我认为没有任何优势。
AccessController.doPrivileged考虑直接调用者的保护域。在您的示例中,定义了someMethodCalledFromJavaScript方法的类。如果这是签名jar中的受信任类,则不受信任的Javascript调用它并不重要。