AccessController.doPrivileged是否为JavaScript线程提供已签名小程序的权限?

AccessController.doPrivileged是否为JavaScript线程提供已签名小程序的权限?,java,javascript,security,applet,Java,Javascript,Security,Applet,我看到的是一个签名小程序,它大量使用JavaScript调用。显然,源于JavaScript的线程比直接从Java内部启动的线程沙盒更重。例如,如果JavaScript线程调用小程序并记录导致日志文件滚动的内容,则会引发安全异常。在小程序中直接启动的任何线程都不会遇到此安全异常。log4j的解决方案是使用异步appender 但是,除了其他安全性例外(例如,在已签名的Applet中使用apacheaxis,但在JavaScript线程中使用apacheaxis),没有明显的方法可以使用异步线程。

我看到的是一个签名小程序,它大量使用JavaScript调用。显然,源于JavaScript的线程比直接从Java内部启动的线程沙盒更重。例如,如果JavaScript线程调用小程序并记录导致日志文件滚动的内容,则会引发安全异常。在小程序中直接启动的任何线程都不会遇到此安全异常。log4j的解决方案是使用异步appender

但是,除了其他安全性例外(例如,在已签名的Applet中使用apacheaxis,但在JavaScript线程中使用apacheaxis),没有明显的方法可以使用异步线程。假设我有下面的代码,如果从Java线程调用,它将工作,如果通过JavaScript调用,它将失败,并出现SecurityException:

public void someMethodCalledFromJavaScript() {
  // Stuff that would throw a SecurityException
}
我看到以下三个选项,但它们可能并不都有效。为了便于讨论,请忽略执行是同步还是异步,因为这很容易管理。我很难理解安全模型的细节。以下是我的三个潜在选择:

  • 启动一个新线程(此线程是否有效?)

  • 让小程序随时准备好一个线程,该线程通过JavaScript源线程触发(此处的代码高度简化):

  • 使用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调用签名小程序的一般情况,以及我如何允许源自JavaScript的线程与签名小程序的priv一起运行,就好像它是源自小程序内部的线程一样


以上哪些选择甚至有效,哪些比其他选择更好,以及为什么。

我会选择doPrivileged。请注意,每个有权访问您的小程序的人都可以下载它并将其放在他们的站点上,并使用自己的恶意javascript以您无法想象的方式调用它

其他解决方案的安全含义几乎相同(编辑:尽管创建新线程不起作用,正如Longpoke指出的那样),但它们更复杂。所以我看不出他们有什么优势

AccessController.doPrivileged只考虑直接调用方的保护域。在您的示例中,定义了方法someMethodCalledFromJavaScript的类。如果这是签名jar中的受信任类,那么不受信任的Javascript调用它并不重要。

  • “启动一个新线程(此线程是否有效?”
由于以下原因,无法正常工作

  • 让小程序随时准备好一个线程,该线程通过JavaScript源线程触发
当然会起作用,但这比调用
doPrivileged
更痛苦,但在语义上也有同样的效果

  • 使用AccessController.doPrivileged
是的,这会有用的


每次访问控制检查都会检查当前线程堆栈上的所有堆栈帧集(包括递归地导致当前线程实例化的堆栈帧)。如果存在
doPrivileged
帧,则该帧之前的帧不包括在集合中(但包括实际的
doPrivileged
帧)

如果要检查的权限不在该集中的每个帧中,则检查失败

换句话说,线程的当前权限是该集合中权限的交集

因此,例如,如果特权代码
doPrivileged
s试图打开文件的某个非特权代码,检查将失败。同样,如果非特权代码
doPrivileged
s打开文件的特权代码,检查将失败。但是,如果非特权代码调用特权代码,特权代码依次调用
doPrivileged
打开文件,检查将成功

理论上,您应该只能授予Java代码库所需的特权(可能是访问某个独立目录),然后授予将使用此特权代码的JavaScript代码相同的特权,但我怀疑任何浏览器都不具备此类功能。我很惊讶JavaScript甚至在Java之外的另一个保护域中运行

我从来没有做过JavaScriptJava互操作,但似乎不管你要做什么,都必须让JavaScript调用的方法在其整个主体上使用
doPrivileged



编辑:正如Sami所说,在调用特权代码中的
doPrivileged
块(并读取他的答案)时要小心。

每次访问控制检查都会检查所有堆栈帧的交叉点(包括递归地导致当前线程实例化的堆栈帧)。如果被检查的特权不在该交叉点的每一帧中,它将失败。如果存在
doPrivileged
帧,则忽略该帧之前的所有帧。因此,例如,如果您
doPrivileged
某个试图打开文件的非特权代码,检查将失败。同样,如果未受信任的代码
doPrivilege
s打开文件的受信任代码,检查将失败。但是如果不受信任的代码调用受信任的代码,而受信任的代码反过来调用
doPrivilege
打开文件,检查将成功。@Longpoke:为什么不写
public void someMethodCalledFromJavaScript() {
  AccessController.doPrivileged(new PrivilegedAction() {
    public Object run() {
      // Stuff that would throw a SecurityException
      return null;
    }
  });
}
java.security.AccessControlException: access denied (java.lang.RuntimePermission accessDeclaredMembers)