【问题标题】:PrivilegedActionException trying to invoke a signed Java applet from JavaScriptPrivilegedActionException 试图从 JavaScript 调用签名的 Java 小程序
【发布时间】:2015-05-10 13:26:25
【问题描述】:

首先,我不是 Java 开发人员。我必须创建一个 Java 小程序来调用我从浏览器编写的本机 DLL 中的一些代码。

我使用 JNA 加载本机 DLL 并调用其方法。
我已使用自签名证书对小程序进行了签名。
浏览器询问我是否允许执行小程序。
加载我的 DLL 的小程序代码包含在 AccessController.doPrivileged 块中。

像这样:

public String Test()
{
    pHelper = AccessController.doPrivileged(new PrivilegedAction<IHelper>() 
    {
        @Override
        public IHelper run() 
        {
            return (IHelper)Native.loadLibrary("Helper", IHelper.class);
        }
    });

    return "test";
}

代码在 Eclipse 中调试时运行良好。

从 JavaScript 调用时不起作用。导致 PrivilegedActionException。

如果我删除整个 AccessController.doPrivileged 块并仅保留 return "test",则代码会在从 JavaScript 调用时运行。任何不需要特权的代码在从 JavaScript 调用时都可以正常运行。

在 Windows 8.1 64 位上从 Chrome 版本 40.something 和 Firefox 36 测试。 本机 DLL 是 32 位以及用于运行小程序的 JRE。

有什么建议吗?

【问题讨论】:

  • (抓挠头)我会预料到相反的结果! “任何提示?” 检查bug database,如果您找不到任何可以解释它的东西,请提出一个新的。什么是浏览器(品牌和版本)?
  • @AndrewThompson 我已经编辑了这个问题,其中包含一些有关环境的信息以及一些关于什么有效和什么无效的说明。

标签: java javascript security applet jna


【解决方案1】:

我从未解开这个特殊的谜团。但是,我能够找到一种解决方法,这要归功于我的小程序设计规范,它不需要公开任何需要调用来执行特权操作的小程序方法。

我发现在applet init() 函数中执行特权操作是可行的。只有通过从 JavaScript 调用执行的特权操作似乎会导致问题。考虑以下代码。

public class MyApplet extends JApplet {
    private IHelper pHelper = null;
    private MyReturnedInfo pInfo = null;

    public void init() {
        pHelper = (IHelper)Native.loadLibrary("Helper", IHelper.class);
        if (pHelper != null) {
            pInfo = pHelper.GetInfo();
        }
    }

    public String GetInfoString() {
        if (pInfo != null) {
            // need to call toString to convert from native wide char to something JavaScript will be able to interpret
            return pInfo.MyInfoString.toString(); 
        }
        return null;
    }
}

加载此小程序后,从 JavaScript 调用 document.myApplet.GetInfoString()(假设小程序具有 ID“myApplet”)将返回所需的信息。

有趣的是,在使用由 VeriSign 等受信任机构颁发的证书对小程序进行签名后,即使这在 IE 中也不起作用,而在 FF 和 Chrome 中却可以正常工作。我已经看到签名的 Java 小程序在 IE 中从 JavaScript 调用时可以正常工作,但我想我的小程序很特别,因为它需要清单中的 all-permissions 属性,而 IE 可能不喜欢这样。这是一个猜测。但是,我也从未找到真正的原因,因为我能够求助于另一种解决方法。 :) 如果您正在阅读此答案,那么我敢打赌您也会对此感兴趣。

Java 小程序允许我们提供额外的参数,我们可以通过从init() 函数内部调用this.getParameter() 来获得这些参数。另外,如果我们允许applet通过使用mayscript属性从我们的HTML文档中调用JavaScript函数,我们可以很容易地结合这两个事实来提供JavaScript函数供applet在从我们的本机DLL中获取信息后调用。

假设在我们的 HTML 中,我们这样定义 JavaScript。

<script type="text/javascript" src="https://www.java.com/js/deployJava.js"></script>
<script type="text/javascript">
    var attributes = {
        id: "myApplet",
        name: "myApplet",
        code: "MyApplet.class",
        mayscript: "true",
        scriptable: "true",
        archive: "/path(s)/to/jar(s)",
        width: 0,
        height: 0
   };

    var params = {
        "AppletReady": "appletInitialized",
    };

    // For convenience, it's easier to deploy the applet using deployJava,
    // so it writes the applet HTML tag for us after checking if Java is installed.
    // We have included it above.
    deployJava.runApplet(attributes, params, "1.8.0");

    function appletInitialized(myString, someOtherArgument) {
        // do something with your parameters
        // NOTE: do NOT call alert() from this function! 
        // Because it will most likely cause your browser to freeze, 
        // I've found that's also one of the things Java doesn't like.
    };
</script>

然后,我们将 Java 小程序代码修改为如下所示。

public class MyApplet extends JApplet {
    private IHelper pHelper = null;
    private MyReturnedInfo pInfo = null;

    public void init() {
        // Read the AppletReady parameter as passed from JavaScript
        String paramKey = "AppletReady";
        String jsLoadedCallback = this.getParameter(paramKey);

        // Load the library and get the information
        pHelper = (IHelper)Native.loadLibrary("Helper", IHelper.class);
        if (pHelper != null) {
            pInfo = pHelper.GetInfo();
            if (pInfo != null && jsLoadedCallback != null) {
                // Get the window which contains "this" applet
                JSObject jsObject = JSObject.getWindow(this);

                // Call the provided JavaScript function.
                // You can use as many parameters as you need.
                jsObject.call(jsLoadedCallback, new Object[] {
                        pInfo.MyInfoString.toString(),
                        pInfo.SomeOtherStringMaybe.toString()
                });
            }
        }
    }
}

但是,如果您需要小程序在运行时动态调用您的本地 DLL 方法(IE 您需要小程序公开需要调用以动态执行特权操作的函数)此解决方案将不适合您并且您已经出局了幸运的是,至少如果使用 JNA。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-25
    • 2010-09-08
    • 2011-04-05
    • 2014-08-15
    • 2013-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多