题目与适用场景
一个 HTTPS 网页要帮助用户配置 USB 设备。用户点击“连接设备”后,浏览器应显示明确授权提示,页面要处理不支持的浏览器、嵌入 iframe、设备断开、权限被拒绝和刷新恢复。
请说明能力检测、用户手势、来源与 Permissions Policy、设备筛选、数据最小化、错误体验、渐进增强和测试策略。页面不能在加载时静默扫描或把设备数据发送到第三方分析服务。
面试官在考察什么
面试官看你是否理解 WebUSB 是受权限控制的强大 Web API,而不是普通的 DOM 设备列表。MDN 说明浏览器会在连接请求时询问用户;Permissions API 的结果会受安全上下文、Permissions Policy、用户交互和提示状态共同影响。
优秀回答会把权限授予来源、顶层页面、嵌入策略、设备过滤和连接生命周期一起考虑。Chrome 文档也强调由用户作出最终授权决定,并建议显式设置 Permissions Policy。前端方案还应遵守渐进增强,让没有 WebUSB 的用户仍能完成说明、下载或转向原生工具。
30 秒回答框架
“页面先检测安全上下文和 navigator.usb 能力,用普通说明和原生工具链接作为降级。用户点击按钮时才调用 requestDevice(),并用精确的厂商和产品过滤器减少误选。响应头的 Permissions Policy 只允许可信来源,嵌入页面默认拒绝。连接后只读取完成任务所需的接口,监听断开事件并提示重新连接。拒绝、断开和浏览器不支持都显示下一步,不把权限错误当成服务器故障。”
分步深入设计
第一步:确定信任边界和业务目标
明确页面只需配置哪些命令和数据,设备是否含有敏感信息,是否必须通过 WebUSB。若设备已有更专用的浏览器 API 或原生工具,应优先评估。前端不应把底层 USB 协议细节暴露给用户,也不应为“方便诊断”读取全部接口。
第二步:做能力检测与渐进增强
检查 HTTPS、浏览器能力和必要的 API 方法。没有能力时提供文档、驱动下载、原生应用或人工支持路径,核心说明仍可阅读。能力检测只决定增强分支,不能假设实现了 API 就一定能获得授权。
第三步:把授权绑定到用户手势
requestDevice() 应由明确的点击或键盘操作触发,按钮文案说明会弹出浏览器权限提示。不要在页面加载、定时器、隐藏 iframe 或异步回调里偷偷请求。请求失败时区分用户取消、策略阻止、浏览器不支持和设备未匹配,但向用户显示安全且可行动的下一步。
第四步:收紧来源和 Permissions Policy
在响应头中显式配置 Permissions-Policy: usb=(self) 或更窄的可信来源列表。若页面被嵌入,确认顶层来源、iframe 的 allow 属性和策略共同允许;不把权限开放给所有第三方。CSP、Trusted Types 和依赖审计继续保护页面本身。
第五步:精确筛选并最小化设备访问
过滤器限制厂商、产品或协议,避免把无关设备展示给用户。连接后枚举必要的配置和接口,设置读写超时与消息大小上限,校验设备响应格式。关闭页面或完成任务时释放接口;不把序列号、原始包或用户身份绑定数据写入分析日志。
第六步:处理连接、断开与刷新
监听 connect 和 disconnect 事件,展示设备名称、当前步骤和重连操作。断开时停止轮询并清理句柄;重连要再次确认设备筛选和当前任务。刷新后的页面不能假定之前的权限或连接仍可用,应通过已授权设备列表和用户主动选择恢复。
第七步:设计错误和隐私体验
用户取消授权不应显示“系统故障”。策略阻止要提示管理员或页面嵌入者,设备未匹配要指导用户插入正确型号。错误日志记录稳定的类别和关联 ID,不记录原始设备数据。向第三方发送诊断前要征得单独同意并脱敏。
第八步:验证跨环境与安全回归
测试不安全上下文、不同浏览器、iframe、策略阻止、用户拒绝、无匹配设备、重复点击、设备断开、刷新、睡眠唤醒和恶意设备响应。检查请求是否始终由手势触发,策略是否只允许预期来源,以及页面在降级模式仍可完成帮助流程。
取舍、边界与信息增益
更窄的设备过滤器减少误选与隐私暴露,却可能让旧固件无法匹配;可以在版本化配置中维护明确兼容范围。自动重连改善体验,但不能绕过新的用户选择或把旧设备句柄当作可信状态。
Permissions Policy 能限制嵌入来源,却不是设备本身的授权;浏览器提示仍由用户决定。渐进增强增加设计和测试成本,但能把浏览器能力差异转化为清晰下一步,而不是空白页面。
高质量示范回答
“我会把 WebUSB 当作受来源和用户授权约束的增强能力。页面在 HTTPS 下检测 API,不支持时提供原生工具或说明。只有用户点击连接按钮时才调用 requestDevice(),并使用精确过滤器。响应头只允许可信来源使用 USB,嵌入 iframe 还要核对顶层策略和 allow。
连接后只访问完成配置所需的接口,校验响应、限制超时和数据大小,不把原始包写日志。监听断开,清理句柄并提示重新连接;刷新后要求用户重新选择。取消、策略阻止、未匹配和不支持分别给出下一步。测试覆盖跨浏览器、iframe、设备断开、恶意响应和降级体验。”
常见错误
- 页面加载时自动调用
requestDevice()。 权限请求必须对应用户明确手势。 - 把 WebUSB 当作普通设备枚举。 它受安全上下文、策略和浏览器权限共同限制。
- 过滤器为空或过宽。 用户可能误选无关设备,页面也读取不必要数据。
- 把 USB 权限开放给所有 iframe。 第三方来源会扩大设备暴露面。
- 用旧连接句柄自动恢复。 刷新、断开和权限状态都可能已改变。
- 把原始设备包写入日志。 诊断数据可能包含敏感信息或可识别序列号。
- 只支持 Chromium。 不支持 WebUSB 的用户需要可用的降级路径。
- 把拒绝授权显示成服务器错误。 用户应知道如何重试或联系管理员。
追问与参考答案
为什么必须由用户手势触发?
设备访问会影响隐私和安全,浏览器需要让用户明确知道哪一个来源请求哪一个设备。手势也是权限提示时机的约束。
Permissions Policy 和浏览器提示是什么关系?
策略先决定文档是否有资格使用能力;即使策略允许,浏览器仍会根据来源、上下文和用户选择显示提示。两层都通过才可能连接。
如何支持设备断开后的重连?
停止读写和轮询,清理句柄,监听重新连接事件,并让用户确认匹配设备。不能在后台无限重试或假定旧授权仍覆盖新设备。
为什么不读取所有设备接口做诊断?
最小访问减少隐私、协议误操作和驱动兼容风险。需要诊断时应使用明确的用户动作、最小字段和单独的日志同意。
不支持 WebUSB 时怎么办?
提供说明、驱动或原生工具下载、浏览器兼容提示和人工支持。核心配置目标不应只剩一个空白的“请换浏览器”。