在浏览器沙箱中运行时,签名的 Java 小程序是否可以访问 USB 外围设备?
我已经实现了一个 Java 包,其功能是操作通过 USB 连接到工作站的 POS 打印机和现金抽屉。我还实现了一个小程序来利用该包的功能,希望能够由 POS 网站调用它。
当小程序在 Eclipse 中运行时,一切顺利。当小程序在浏览器中运行时,我的包似乎无法访问通过 USB 连接的外围设备。我从第三方 (JavaPOS) 代码收到一条错误,指出:
jpos.JposException:设备 通讯渠道无法 打开,检查设备并重试。
该小程序使用自认证进行签名。我会发布一些代码,但错误是从埋藏在正在使用的 POS 打印机的制造商特定驱动程序中的某个地方引发的。
我假设问题是,在浏览器沙箱内,小程序无法访问通过 USB 连接的外围设备。
可能是这样吗?如果是这样,是否可以从签名的 Applet 中访问 USB 外围设备?
如果小程序无法访问 USB 外围设备,那么网站如何调用可以访问 USB 外围设备的代码呢?
I've implemented a Java package with functionality to operate a POS printer and cash drawer connected to the workstation via USB. I've also implemented an applet to utilize the functionality of this package with the hopes of having it invoked by a POS website.
When the applet is run from within Eclipse, all goes well. When the applet is run from within a browser it seems that my package is unable to access the peripherals connected via USB. I get an error from the third party (JavaPOS) code stating:
jpos.JposException: The device
communications channel could not be
opened, check the device and retry.
The applet is signed with a self-cert. I'd post some code but the error is thrown from somewhere buried in manufacturer-specific drivers for the POS printer in use.
I'm assuming the issue is that, from within the browser sandbox, the applet does not have access to the peripherals connected via USB.
Could this be the case? If so, is there anyway to access USB peripherals from within a signed Applet?
If an applet can't access USB peripherals, how could a web site invoke code that can?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
为了解决这个具体问题(并避免下面的评论中涉及的具体技术),是的,签名的 Java Applet 可以访问 USB 外设。 “沙箱”是当您运行签名的小程序时您有能力“突破”的地方。
但出于安全原因,仅对小程序进行签名并不会自动授予对沙箱之外的项目的访问权限。
PrivelegedAction
似乎是访问特权系统组件(例如打印机)的首选方法。 Oracle 在此处提供了有关这些特权操作的更多信息:http: //docs.oracle.com/javase/7/docs/api/java/security/AccessController.html此外,从 Web 浏览器执行此类操作时需要考虑几个因素,因为 Java 关心操作的来源从。
例如,如果您要使用小程序 init() 方法中的
FileWriter
类将文件写入文件系统(即$HOME/Desktop/text.txt
),签名的 Applet通常会允许它。将其包装到PrivilegedAction
中会更好,并且首先使用AccessController.checkPermission(...)
检查权限将是理想的选择。但是,当直接从 JavaScript(而不是从 init())调用时,
FileWriter
会被阻止:为了规避此问题,有些人选择使用
PrivelegedAction
,但是如果该操作采取很长一段时间后,您会注意到它会阻塞 UI,这在网页中是非常糟糕的做法(并且可能导致浏览器死锁)。此外,您的问题具体询问了有关访问 USB 外围设备的问题,这通常是通过迭代人机接口设备来完成的。 HID 并不是 Java 本身直接支持的东西(截至编写本文/JRE7 为止)。所以,是的,签名的小程序可以与您的 USB 外围设备通信,但您需要使用某种形式的 Java 本机接口 (JNI) 来正确“访问”它们。 JNI 在支持跨平台方面可能会很混乱(即使用 JAR 分发 DLL 和 SO),所以...
大多数 Java Applet 所做的就是访问本地安装的打印机并使用标准 Java 打印库。这就是我们在 qz-print 项目中的做法,您可以在这里自由查看我们的源代码:https://github.com/qzindustries/qz-print/tree/master/qz-print/src/qz 它使用由 init() 触发的线程和触发所有特权函数的布尔标志。
To address this specific question (and avoid the specific technologies involved in the comments following), yes Signed Java Applets have access to USB Peripherals. The "sandbox" is what you have capability to "break out of" when you run a signed applet.
But for security reasons, simply signing the applet does not automatically give access to items outside of the sandbox.
PrivelegedAction
seems to be the preferred method for accessing privileged system components, such as the printer. More about these privileged actions is provided by Oracle here: http://docs.oracle.com/javase/7/docs/api/java/security/AccessController.htmlIn addition, there are several consideration when doing something like this from a web browser as Java cares where the action originates from.
For example, if you were to write a file to the filesystem (i.e.
$HOME/Desktop/text.txt
) using theFileWriter
class in the applet init() method, a Signed Applet would generally allow it. Wrapping this into aPrivilegedAction
would be better, and checking permission first usingAccessController.checkPermission(...)
would be ideal.However,
FileWriter
gets blocked when it's called directly from JavaScript (instead of from init()):To circumvent this issue, some chose to use
PrivelegedAction
, however if the action takes a long time, you'll notice it blocks the UI, which is very bad practice in a web page (and can deadlock the browser).Furthermore, your question asks specifically about accessing a USB peripheral, which is generally done by iterating through the Human Interface Devices. HID is not something Java directly supports natively (yet, as of writing this/JRE7). So yes, a signed applet CAN talk to your USB peripherals, but you would need to use some form of Java Native Interfacing (JNI) to properly "access" them. JNI can be a mess to support cross-platform (i.e. distributing DLLs and SOs with your JAR) so...
What most Java Applets do is access the locally installed printers and use the standard Java Printing libraries. This is how we do it over at the qz-print project and you're free to review our source code here: https://github.com/qzindustries/qz-print/tree/master/qz-print/src/qz which uses threads fired by init() and boolean flags to fire all privileged functions.
我不确定你的问题的答案,但有一个实验应该可以进一步阐明这个问题。
在
Applet.init()
的开头几行调用System.setSecurityManager(null)
。然后尝试连接 USB。setSecurityManager(null)
的调用将成功,并删除SecurityManager
的最后残余部分。 (是的,即使受信任的小程序也有安全管理器,但它的限制比沙盒应用程序的安全管理器要少得多。)请注意,我并不建议将这样的代码投入生产。如果您的小程序与其他小程序在同一 JRE 中运行,则取消 SM 也可能会提升其他小程序的权限。
I am not sure of the answer to your question, but have an experiment that should shed further light on the matter.
In the opening lines of the
Applet.init()
callSystem.setSecurityManager(null)
. Then try to connect to the USB.setSecurityManager(null)
will succeed, and remove the last remnants of theSecurityManager
. (Yes, even trusted applets have a security manager, it is just much less restrictive that the security manager for sand-boxed apps.)Note that I am not suggesting putting code like this into production. If your applet is running in the same JRE as other applets, nullifying the SM could also elevate the privileges of the other applets.
我在 XP 和 Win7 32 位上使用 JRE 1.6 的 Epson TM-H6000III 也遇到了类似的问题。管理员可以使用该设备,但“用户”不能。 Java 控制台报告:
JRE 安装似乎存在权限问题。重新安装JRE很快就解决了问题。
I had a similar problem with an Epson TM-H6000III on XP and Win7 32bit using JRE 1.6. Administrators could use the device, but "Users" could not. Java console was reporting:
It appears the JRE installation had permission issues. Reinstalling JRE quickly cleared the problem.
我收到了 Star Micronics 团队的反馈,他们的“...javapos 驱动程序不支持 Web 浏览器打印。”
顺便说一句,System.setSecurityManager(null) 被证明是消除我遇到的任何似乎与安全相关的问题的好方法。谢谢安德鲁。
I received feedback from the Star Micronics team that their '...javapos drivers do not support web browser printing.'
BTW, System.setSecurityManager(null) turned out to be a great way to disambiguate any issues I was having that seemed to be related to security. Thanks Andrew.