java - 从 Javascript 调用 Java 的 Desktop.open 方法 - 访问被拒绝 java.awt.AWTPermission showWindowWithoutWarningBanner

标签 java javascript security applet

我有一个网络应用程序,需要能够在客户端计算机上本地打开文件,并且能够在编辑后保存文件。 Web 应用程序在服务器上的一个文件夹中生成一个文档,该文件夹通过 WebDAV 和 FTP 共享,并且该文件夹安装在客户端计算机上。

我无法使用 file://类型 URI,因为它不允许保存回服务器。

我打算尝试使用嵌入在 Web 应用程序中处理此文件打开的小型 Java 小程序来解决问题,但我在 Java 中的权限方面遇到了困难。 (Java 不是我的专业领域)。无论如何,我已将代码范围缩小到以下内容:

localfile.html

<html>
<body>
  <input id="input" value="Call from Javascript" type="button" onclick="callApplet('/Users/conor/1.txt')">
  <script type='text/javascript'>
  function callApplet(path) {
    applet = document.getElementById('localfile');
    applet.openFile(path);
  }
  </script>
<applet id="localfile" code="localfile.class" archive="localfile.jar"  width="150" height="50"></applet>
</body>
</html>

localfile.java

import java.applet.*;
import java.awt.*;
import java.util.*;
import java.lang.*;
import java.text.*;
import java.awt.event.*;
import java.io.*;

import java.security.*;

public class localfile extends Applet {
  public localfile() {
    Panel p = new Panel();
    p.add(new Button("Call from Java"));
    add("North",p);
  }
  public void openFile(String path) {
    System.out.println("File: " + path);
    final File ffile = new File(path);
    System.out.println("Got file.");
    if (Desktop.isDesktopSupported()) {
      System.out.println("Desktop is supported.");
      final Desktop desktop = Desktop.getDesktop();
      System.out.println("Got Desktop Handle.");
      try {
        desktop.open(ffile);
      } catch(Exception ex) {
        ex.printStackTrace();
      }
      System.out.println("File Opened.");
    }
  }

  public boolean action(Event evt, Object arg) {
    openFile("/Users/conor/1.txt");
    return true;
  }
}

我已经编译、创建了一个 jar 文件并从 java 源代码对其进行了签名。

这会生成一个带有两个按钮的页面 - 一个 Java 按钮(用于测试)和一个 Javascript 按钮。 Java 按钮按预期工作正常 - 我可以保存文件等。不过我想将文件路径传递给小程序,所以它实际上是我希望开始工作的 Javascript 按钮。 Javascript 会抛出以下错误:

堆栈跟踪

java.security.AccessControlException: access denied ("java.awt.AWTPermission" "showWindowWithoutWarningBanner")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366)
at java.security.AccessController.checkPermission(AccessController.java:560)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at java.awt.Desktop.checkAWTPermission(Desktop.java:239)
at java.awt.Desktop.open(Desktop.java:267)
at localfile.openFile(localfile.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at sun.plugin.javascript.JSInvoke.invoke(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at sun.plugin.javascript.JSClassLoader.invoke(Unknown Source)
at sun.plugin2.liveconnect.JavaClass$MethodInfo.invoke(Unknown Source)
at sun.plugin2.liveconnect.JavaClass$MemberBundle.invoke(Unknown Source)
at sun.plugin2.liveconnect.JavaClass.invoke0(Unknown Source)
at sun.plugin2.liveconnect.JavaClass.invoke(Unknown Source)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$DefaultInvocationDelegate.invoke(Unknown Source)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo.doObjectOp(Unknown Source)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$LiveConnectWorker.run(Unknown Source)
at java.lang.Thread.run(Thread.java:722)

我还尝试将desktop.open调用嵌入到doPrivileged block 中,如下所示:

  AccessController.doPrivileged(new PrivilegedAction() {
    public Object run() {
      try {
        desktop.open(ffile);
      } catch(Exception ex) {
        ex.printStackTrace();
      }
      return null;
    }
  });

但这会引发 javascript 和 java 按钮的错误,如下所示:

java.lang.SecurityException: class "localfile$1" does not match trust level of other classes in the same package

如有任何帮助,我们将不胜感激。

最佳答案

让它工作,所以我想在这里发布解决方案......

当我编译带有 doPrivileged 调用的 java 文件时,javac 编译器创建两个文件 - localfile.class 和 localfile$1.class。我最初不确定 localfile$1.class 是什么,只是假设它是某种临时文件。然而,它是一个与 doPrilileged block 中的匿名类相对应的类文件,需要包含在 .jar 文件中并正确签名。

所以无论如何,html文件和以前一样,最终的java文件如下:

localfile.java

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.security.*;

public class localfile extends Applet {

private static final long serialVersionUID = 1L;

public localfile() {
  Panel p = new Panel();
  p.add(new Button("Call from Java"));
  add("North",p);
}

public void openFile(String path) {
  System.out.println("File: " + path);
  final File ffile = new File(path);
  System.out.println("Got file.");
  if (Desktop.isDesktopSupported()) {
    System.out.println("Desktop is supported.");
    final Desktop desktop = Desktop.getDesktop();
    System.out.println("Got Desktop Handle.");
    AccessController.doPrivileged(new PrivilegedAction() {
      public Object run() {
        try {
          desktop.open(ffile);
        } catch(Exception ex) {
          ex.printStackTrace();
        }
        return null;
      }
    });
    System.out.println("File Opened.");
  }
}

public boolean action(Event evt, Object arg) {
  openFile("/Users/conor/1.txt");
  return true;
}

}

我还发现不需要让 html 文件中的 javascript 创建小程序并将其插入到 DOM 中。我认为 @VGR 链接的链接中提到了这一点,但没有它它对我也有用。

感谢大家的帮助!

关于java - 从 Javascript 调用 Java 的 Desktop.open 方法 - 访问被拒绝 java.awt.AWTPermission showWindowWithoutWarningBanner,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14568118/

相关文章:

java - 无需中介即可从网络服务器打印到热敏打印机

php - 了解 PHP 和 MySQL 安全性基础知识

security - Internet Explorer 跨域 iframe 登录

ios - 苹果手机 : is there any secure way to establish 2-way SSL from an application

java - Play 2 : Difference between appDependencies and libraryDependencies?

java - JToggleButton.其中一个已选定,其他已取消选定

java - 尝试在Java中找到扫描仪用户输入的最小数量

javascript - 在 Canvas 上绘制 3 个圆圈的重叠部分

javascript - React + useState + Array + Mutation = 错误

javascript - 如何在vue组件中包含外部js