0 引言
基于浏览器的B/S架构应用程序(此后简称Web应用)开发过程中,常出现Web应用与用户端硬件设备进行交互操作的场景,如Web应用需访问用户端的摄像头进行拍照或录像、访问用户端的卡片打印机打印卡片、访问用户端串口设备等。虽然浏览器提供了mediaDevices、WebUSB、WebBluetooth等设备操作方法,但现代浏览器由于同源策略、沙箱、内容安全策略以及其他安全机制共同限制了Web应用直接操作硬件设备的能力。陈欣华[1]在研究浏览器安全机制时,总结出浏览器主要安全机制包括同源策略、浏览器沙箱、内容安全策略、Cookie机制等。出于保护用户信息安全的目的,浏览器限制了Web应用直接访问用户系统中的硬件设备,Web应用对硬件设备的访问能力因此被极大削弱。为了实现在Web应用中访问用户硬件设备的目的,必须要突破浏览器的安全性限制,而且在突破浏览器安全限制的同时不能使用户的本地设备出现其他安全性问题。
解决这一问题的传统方式是开发浏览器扩展插件,浏览器插件的实现技术主要有ActiveX控件和NPAPI插件两种方式,云吉[2]等人在2015年做过此类研究,其中Active控件对当今主流浏览器支持不佳,只能在微软的浏览器上使用,NPAPI插件技术受浏览器沙箱机制限制,在现代浏览器中也不能直接访问本地设备。在Web应用中能够操作用户硬件设备,对于医疗设备控制、工控硬件控制等场景是非常具有实用性的。因此,本研究旨在设计一种不依赖于传统浏览器插件、具有更好跨平台性和安全性的新型解决方案,通过在本地构建一个轻量级服务,以协议代理的方式,为Web应用安全地"解锁"访问本地硬件的能力。
1 方案设计
1.1 关键技术
当今主流浏览器都支持HTML5,为了兼容市场上主流的浏览器,严伟苗[3]等人采用了WebSocket技术来突破浏览器安全限制,以此证明使用WebSocket确实是一种有效的手段;Nikola Kirilov[4]通过对比研究证明了WebSocket技术在数据传输方面比HTTP协议传输数据的效率更高,选择WebSocket技术是一种有效解决本研究问题的好方法。WebSocket是HTML5中的一种协议,其设计目标是提供一种机制使浏览器不需要依赖HTTP连接,使浏览器与服务器之间保持长连接以及双向通信。WebSocket协议基于TCP协议,包含握手过程和数据传输两部分。握手过程中由客户端发送一个HTTP升级请求,表明浏览器将使用WebSocket连接,服务端同意连接后,两端即可发起数据传输,WebSocket协议可与TLS/SSL等安全传输层协议结合使其保证通信的安全性[5]。
基于WebSocket的消息通信协议,浏览器与服务端通信的消息采用了JSON数据格式来描述。丁承君[6]等人在对XML、JSON、Protobuf做过序列化性能比较研究,其结果反映出JSON格式描述的数据比XML格式描述的数据在序列化后占用的存储空间更少,而且JSON格式描述的数据可读性好,数据的自描述能力强。
1.2 总体方案设计
为突破Web应用访问本地硬件设备被浏览器限制的问题,本方案中将用户所使用的浏览器作为WebSocket的客户端,用户本地系统作为WebSocket的服务端,总体解决方案设计见图1所示。服务端WebSocket连接模块用于接收来自浏览器的连接请求并将服务端的处理结果以规定的数据格式向浏览器做出响应;命令处理模块负责将接收到的格式消息转换成对设备操作的命令;数据处理模块负责调用具体的设备SDK从而实现硬件设备操作;服务配置模块负责服务端的参数配置,如服务端端口配置、认证账户、密码安全性配置等。

图1 解决方案总体设计结构图
该方案中服务端作为后台服务程序运行于用户的本地系统上,后台服务启动后即开启WebSocket服务等待Web浏览器连接。Web浏览器作为客户端,用户在使用Web应用时,如需使用本地硬件设备,通过WebSocket客户端与服务端建立连接,然后发送对应设备的命令和相关参数。
此解决方案主要目的是突破浏览器安全性限制并操作本地硬件设备,因此将方案命名为"WebNaket",即Web Native Socket各取一部分组合而成,意为Web应用中通过WebSocket方法访问本地(Native)设备。
1.3 通信协议设计
WebSocket客户端与服务端建立连接后即可双向发送通信数据,WebSocket的协议只明确了数据消息头的定义,将数据消息的应用协议交给软件定义并实现,此处的数据消息通信协议参考了翁金芳[7]等人所研究的串口调试助手。为了WebSocket客户端能方便操作不同的设备,同时兼顾消息的可读性,采用JSON格式将WebSocket客户端向服务端发送的消息规范化,将这些规范化的数据消息称为通信命令。使用JSON格式描述的通信命令格式如下所示:

其中cmd表示命令名称,此项使用字符串表示,通信命令中cmd必填;args表示执行当前命令所需的参数,以数组形式表示,参数的数量可根据命令需要任意扩展,args是可选项,如果cmd对应的命令无需参数可不传args参数。在args参数数组中,使用name表示参数的名称,value表示该参数的值,参数值可使用字符串、数字、布尔三种类型。在命令定义时可按照不同的硬件设备分成不同的命令类型,表1展示了部分命令的定义形式,以CAMERA为前缀的表示此命令属于摄像头操作命令,以PRINTER为前缀的表示此命令属于打印机操作命令,无前缀的命令不属于设备操作命令。
表1 命令定义示例表
|---------------|----------|
| 命令名称 | 命令说明 |
| LOGIN | 身份认证 |
| DISCONNECT | 断开客户端连接 |
| CAMERA:OPEN | 打开摄像头 |
| CAMERA:CLOSE | 关闭摄像头 |
| PRINTER:LIST | 获取打印机列表 |
| PRINTER:PRINT | 打印信息 |
| PORT:OPEN | 打开串口 |
| PORT:CLOSE | 关闭串口 |
由于WebSocket是全双工通信,前端发送的命令请求在服务端需要一定的时间才能执行完成并返回,浏览器端收到返回消息后,需要能快速判断出此返回消息所对应的请求命令,因此对服务端返回的结果消息也采用JSON格式来描述。在返回消息中cmd字段表示对应的请求命令;code为0表示执行成功,code字段不为0表示命令执行失败,执行失败的原因在msg字段中描述;如果命令成功执行,执行的结果数据放入data字段内。响应消息参数含义见表2所示:
表2 响应数据参数说明
|--------|--------|--------|
| 字段 | 必须 | 说明 |
| cmd | 是 | 请求命令 |
| code | 是 | 结果状态码 |
| msg | 是 | 结果状态信息 |
| data | 否 | 执行结果数据 |
2 方案实现
2.1 服务端实现
由于服务端需要与本地硬件设备交互,故服务端采用C++编程环境来实现。C++语言具有高性能执行的特性,对硬件设备有较好的操作能力,而且作为面向对象的程序设计语言,具有封装、继承、多态等特性,程序代码复用性强,非常适合于本解决方案访问不同硬件设备的场景。
服务端创建一个Socket网络服务程序,绑定并监听端口(默认3001),然后等待客户端连接。来自客户端的连接必须是WebSocket协议,当服务端发现连接不是WebSocket协议时将自动断开此连接。如果客户端连接采用了WebSocket协议,服务端将创建新线程用于接收、解析和执行来自客户端的命令。服务端无法识别的命令将被忽略。服务端发现客户端已断开连接时,将回收此线程的相关资源。服务端与客户端的连接处理过程见图2所示。

图2 服务端与客户端连接过程
客户端(浏览器)操作硬件设备流程见图3所示。客户端连接上服务端后(第1、2步),首先要进行连接身份认证(第3、4、5步),服务端通过身份认证后,客户端可发起设备操作,否则服务端将断开连接。客户端连接通过身份认证后,可发起对设备操作的命令,命令以JSON格式异步发送给服务端(第6步),服务端解析JSON格式并识别命令(第7步),选择与命令对应的设备SDK并执行该设备操作(第8步),然后将设备操作的反馈信息返回到客户端(第9、10步)。

图3 硬件设备操作流程图
2.2 Web端SDK
与服务端所提供的服务程序对应,为方便在Web应用中操作硬件设备,在Web端提供一套便于操作服务端设备的编程SDK(Software Development Kit),该SDK使用Javascript实现,所提供的SDK中包含了连接后端服务、断开后端服务、设备操作三类方法。
以操作本地摄像头设备为例(打印机访问、串口访问的Web端SDK与此相似),以下代码演示了连接后端服务、断开后端服务以及操作摄像头设备的过程:
class WebCamera {
constructor(protocal, host, port, username, password, onMsgFun) { ...... }
Connect(){
this.socket = new WebSocket(url);
this.socket.onopen = function() { ...... }
this.socket.onmessage = async function(event) { ...... }
}
Open(index){
this.socket.send(JSON.stringify({ cmd: "CAMERA:OPEN",
args: [{ name: "index", value: index }]
})); }
Close(){ this.socket.send(JSON.stringify({ cmd: "CAMERA:CLOSE" })); }
}
类WebCamera的构造方法(constructor)接收后端服务连接协议(默认ws)、主机名、端口、认证账户、认证密码、响应消息回调函数等参数。Connect方法主要用于建立与后端服务的连接,首先将相关参数组合成所需连接字符串(url)并交给WebSocket对象,然后为WebSocket对象添加事件响应方法,如在onopen事件响应方法中执行服务连接认证。当后端服务完成设备操作后,返回数据会进入onmessage事件方法中,在此事件方法中可调用前端程序自定义回调函数;Open方法用于操作摄像头设备,由传入的index参数指定当前主机所安装的摄像头设备序号;设备使用完成后,调用Close方法关闭已打开的设备以及关闭后端服务连接等操作。
3 应用效果
在基于Web的体检管理系统中,需要读取到检人员提供的身份证信息,同时要对到检人员拍照确认,需要调用打印机打印到检人员的导检单等功能,这些在Web应用中的功能都需要操作用户电脑上安装的硬件设备。为验证本文方案的可行性,实现了服务端与Web端SDK,将服务端与Web端SDK打包并发布为WebNaket软件包。
将WebNaket软件包安装至用户所操作的电脑上,WebNaket安装包在用户的电脑上创建了一项后台服务程序(服务名为WebNaketService)。在基于Web的体检管理系统中使用Web端SDK接入身份证读卡器与摄像头,用户端打开Web应用,进入人员拍照页面后,可成功实现拍照功能。在此过程中,浏览器不会因调用摄像头而提示安全性问题,也无需配置HTTPS证书,功能验证效果良好。在案例应用中,调用摄像头拍照无明显延迟感,通过Web前端编程,可以将设备返回的图像信息按照任意需求处理。此处不再对打印功能及串口访问功能的验证进行赘述。
对比WebNaket与浏览器上访问硬件设备的其他方案,各方案的核心能力见表3所示。WebNaket与WebUSB等针对特定总线的API不同,WebNaket方案在理论上可以封装任何类型的本地硬件SDK,无论是串口设备、打印机还是专业的医疗仪器,WebNaket提供了一个更具普适性的解决方案。
表3 WebNaket方案与主流浏览器原生API的核心能力对比
|--------------------|--------------|------------------|---------------|---------------|------------------|
| 能力维度 | WebNaket | mediaDevices | WebRTC | WebUSB | WebBluetooth |
| 设备支持 | 任意设备 | 仅媒体设备 | 仅媒体设备 | USB设备 | 蓝牙设备 |
| HTTPS 强制要求 | 无需证书 | 必须(生产环境) | 必须 | 必须 | 必须 |
| 设备控制能力 | 低层指令级 | 基础媒体控制 | 媒体流控制 | 协议级 | 协议级 |
| 用户交互 | 可静默访问 | 需手动授权 | 需手动授权 | 需手动授权 | 需手动授权 |
| 跨浏览器支持 | 依赖本地服务 | 主流浏览器 | 主流浏览器 | Chrome/Edge为主 | Chrome/Edge为主 |
| 网络依赖 | WebSocket | 本地操作 | P2P 通信需NAT 穿透 | 本地操作 | 本地操作 |
| 典型场景 | 医疗设备/工控硬件 | 视频通话/人脸识别 | 视频会议/远程协作 | USB仪器/加密狗 | 蓝牙标签/健康设备 |
参考文献:
1\]陈欣华.浏览器安全机制研究\[J\].中国管理信息化,2020,23(19):186-187. \[2\]云吉,杨铸,姚严峰.视频监控系统跨浏览器插件的研究与实现\[J\].电子设计工程,2015,23(16):65-67. \[3\]严伟苗,诸葛杨杨,刘瑞,等.基于websocket的适配多种浏览器的插件开发方法\[J\].数字技术与应用,2020,38(02):108+110. \[4\]Nikola Kirilov. Comparison of WebSocket and Hypertext Transfer Protocol for Transfer of Electronic Health Records\[J\]. Studies Health Technology and Informatics,2024,313:124-128. \[5\]IETF.The WebSocket Protocol\[EB/OL\].(2011-12).\[2025-7-14\].https://www.rfc-editor.org/rfc/rfc6455.html. \[6\]丁承君,崔欣,朱雪宏,等.信息物理系统数据格式交换性能研究\[J\].科技通报,2019,35(02):59-63. \[7\]翁金芳,陈文印,陈乐,等.基于WebSocket的串口调试助手设计\[J\].电脑与信息技术,2022,30(06):55-59.