【问题标题】:Do signed java applets have access to USB peripherals when run in the browser sandbox?在浏览器沙箱中运行时,签名的 Java 小程序是否可以访问 USB 外围设备?
【发布时间】:2011-04-17 15:20:50
【问题描述】:

我已经实现了一个 Java 包,该包具有操作通过 USB 连接到工作站的 POS 打印机和现金抽屉的功能。我还实现了一个小程序来利用这个包的功能,希望它被 POS 网站调用。

当小程序在 Eclipse 中运行时,一切顺利。从浏览器中运行小程序时,我的包似乎无法访问通过 USB 连接的外围设备。我从第三方 (JavaPOS) 代码中收到一条错误消息:

jpos.JposException: 设备 沟通渠道不可能 打开,检查设备并重试。

小程序使用自证书签名。我会发布一些代码,但错误是从埋藏在正在使用的 POS 打印机的制造商特定驱动程序中的某个地方抛出的。

我假设问题在于,在浏览器沙箱中,小程序无法访问通过 USB 连接的外围设备。
会是这样吗?如果是这样,是否可以从已签名的 Applet 中访问 USB 外围设备?
如果小程序无法访问 USB 外围设备,那么网站如何调用可以访问的代码?

【问题讨论】:

  • Bozho 似乎是这么认为的:stackoverflow.com/questions/2093707/…(我认为这不是那个问题的重复——其他人可能——但我认为这对你有帮助)。
  • 听起来那个问题中的用户正在自己编写驱动程序。我正在调用一个现有的驱动程序,所以我认为包含 USB API 的 .jar 对我的情况没有帮助。不过还是谢谢。

标签: java applet usb javapos


【解决方案1】:

签名的 Java 小程序在浏览器沙箱中运行时是否可以访问 USB 外围设备?

为了解决这个特定问题(并避免后面的 cmets 中涉及的特定技术),是的,签名 Java 小程序可以访问 USB 外围设备。 “沙盒”是您在运行已签名的小程序时能够“突破”的地方。

但出于安全原因,简单地签署小程序并不会自动授予对沙盒外项目的访问权限。

PrivelegedAction 似乎是访问特权系统组件(例如打印机)的首选方法。 Oracle 在此处提供了有关这些特权操作的更多信息:http://docs.oracle.com/javase/7/docs/api/java/security/AccessController.html

此外,从网络浏览器执行此类操作时有几个考虑因素,因为 Java 关心操作的来源。

public function writeFile() {
    ...
    FileWriter fw = new FileWriter(...);
    ...
}


public void init() {
    writeFile();
}

例如,如果您要在 applet init() 方法中使用 FileWriter 类将文件写入文件系统(即 $HOME/Desktop/text.txt),则签名 Applet通常会允许这样做.将其包装成 PrivilegedAction 会更好,并且首先使用 AccessController.checkPermission(...) 检查权限是理想的。

但是,FileWriter 在直接从 JavaScript(而不是从 init())调用时会被阻止:

var myapplet = document.getElementById('myapplet');
myapplet.writeFile(); // Blocked by Security Framework

为了规避这个问题,有些人选择使用PrivelegedAction,但是如果操作需要很长时间,您会注意到它会阻塞 UI,这在网页中是非常糟糕的做法(并且可能死锁浏览器) .

public void init() {
   ...
   AccessController.doPrivileged(new PrivilegedAction() {
      public Object run() {
         writeFile();
         return null;
      }
   });
   ...
}

此外,您的问题专门询问有关访问 USB 外围设备的问题,这通常是通过迭代人机接口设备来完成的。 HID 不是 Java 本身直接支持的东西(然而,在编写此/JRE7 时)。所以是的,一个签名的小程序可以与您的 USB 外围设备对话,但您需要使用某种形式的 Java 本机接口 (JNI) 来正确“访问”它们。 JNI 支持跨平台(即用你的 JAR 分发 DLL 和 SO)可能会一团糟,所以......

大多数 Java 小程序所做的是访问本地安装的打印机并使用标准 Java 打印库。这就是我们在 qz-print 项目中的做法,您可以在这里查看我们的源代码:https://github.com/qzindustries/qz-print/tree/master/qz-print/src/qz,它使用由 init() 触发的线程和布尔标志来触发所有特权函数。

【讨论】:

    【解决方案2】:

    我不确定你的问题的答案,但有一个实验可以进一步阐明这个问题。

    Applet.init() 调用System.setSecurityManager(null) 的开头行。然后尝试连接到 USB。

    • 如果小程序受信任,则对setSecurityManager(null) 的调用将成功,并删除SecurityManager 的最后剩余部分。 (是的,即使是受信任的小程序也有一个安全管理器,它的限制比沙盒应用的安全管理器要少得多。)
    • 如果现在发现了 USB,则表明受信任的安全管理器发生了变化。最近发生了许多这样的变化。

    请注意,我不建议将这样的代码投入生产。如果您的小程序与其他小程序在同一个 JRE 中运行,则取消 SM 也可以提升其他小程序的权限。

    【讨论】:

    • 感谢您的建议。但是,在尝试访问外围设备之前调用 setSecurityManager(null) 时,我得到了相同的结果。
    【解决方案3】:

    我在使用 JRE 1.6 的 XP 和 Win7 32 位上使用 Epson TM-H6000III 时遇到了类似的问题。管理员可以使用该设备,但“用户”不能。 Java 控制台正在报告:

    Sep 23, 2011 3:38:47 PM com.xxxx.printer.epson.EpsonPrinter findPrinter
    INFO: Error opening PrinterIII: jpos.JposException: 
        Could not connect to service with logicalName = 
        PrinterIII: Exception.message=Property or stream open error.
    

    JRE 安装似乎存在权限问题。重新安装 JRE 很快就解决了这个问题。

    【讨论】:

      【解决方案4】:

      我收到 Star Micronics 团队的反馈,他们的“...javapos 驱动程序不支持 Web 浏览器打印”。

      顺便说一句,System.setSecurityManager(null) 被证明是消除我遇到的任何与安全相关的问题的好方法。谢谢安德鲁。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-10
        • 2021-11-24
        • 2014-01-22
        • 1970-01-01
        相关资源
        最近更新 更多