运动传感器通过校准噪声泄露稳定的设备指纹。iOS 已用权限提示封堵,而 Android 上的 Chrome 至今仍是默认放行、静默可读。
Canvas 和 WebGL 指纹识别读取的是设备如何渲染。传感器指纹识别读取的是完全不同的东西:设备的物理硬件如何运动——或者更准确地说,它如何报告一次从未真实发生过的运动。每一颗加速度计、陀螺仪和磁力计从出厂起就带有微小、永久的制造误差,而这些芯片暴露给网页的原始数据,正携带着这份误差作为一种签名。本文将探讨 DeviceMotion、DeviceOrientation 与 Generic Sensor API 家族如何暴露这一信号,为什么它几乎完全是手机和平板电脑特有的现象,以及那道在 iOS 上封堵了它的权限关卡,为何始终没有出现在 Android 上。
核心要点
DeviceMotionEvent与DeviceOrientationEventAPI 会暴露设备运动硬件的实时读数。更新的 Generic Sensor API 系列类(Accelerometer、Gyroscope)读取的是同一套硬件,但仅 Chromium 支持——Safari 与 Firefox 都未实现。- 制造公差让每一颗加速度计和陀螺仪芯片都带有轻微但一致的偏移与噪声模式——一种校准指纹,它在不同会话、不同浏览器甚至恢复出厂设置后依然保持稳定,因为它烙印在物理硅片本身,而不是任何软件状态里。
- 这是一种移动端专属向量:笔记本电脑和台式机通常根本没有加速度计或陀螺仪,因此该信号几乎只存在于手机和平板电脑上。
- 权限管控是分裂的,而非普遍存在。 自 iOS 13 起,苹果要求必须先弹出明确的权限提示,这确实关闭了该技术在 iOS 上的静默版本。而 Chromium 从不弹窗:它自己的设计文档就把加速度计与陀螺仪定为自动授予。在 Android 上,顶层 HTTPS 页面至今仍可在毫无提示的情况下读取校准噪声。
- BrowserInsight 的指纹检测会将设备暴露的信号一并展示,移动端指纹识别指南则介绍了这一信号如何融入更广泛的移动端追踪图景。
DeviceMotion、DeviceOrientation 与 Generic Sensor API
有两代互相重叠的 API 向网页暴露运动数据。较早的一对——DeviceMotionEvent 与 DeviceOrientationEvent——一旦绑定监听器就会持续触发,以普通事件属性的形式提供加速度、旋转速率和方向角:
window.addEventListener('devicemotion', (event) => {
const { x, y, z } = event.accelerationIncludingGravity;
// 即使设备静止放在桌面上,x、y、z 也会有轻微漂移
});
更新的 Generic Sensor API 家族——Accelerometer、Gyroscope 与 Magnetometer——用专门的传感器对象取代了基于事件的模型,脚本可以直接构造、配置并轮询这些对象。(W3C 的运动传感器说明文档是一份非规范性的工作组说明,有助于理解它们之间的关系;这些接口本身由各自独立的规范定义。)
const sensor = new Accelerometer({ frequency: 60 });
sensor.addEventListener('reading', () => {
console.log(sensor.x, sensor.y, sensor.z);
});
sensor.start();
关于适用范围有两点需要说明。Generic Sensor 系列类是 Chromium 独有的特性:Chrome、Edge 与 Opera 支持它们,而 Safari 与 Firefox 既未实现 Accelerometer 也未实现 Gyroscope,因此那对较早的事件 API 仍是唯一能跨所有引擎工作的途径。此外在 Chromium 内部,Magnetometer 被置于 #enable-generic-sensor-extra-classes 实验标志之后,并未默认开启——普通页面无法像读取加速度计和陀螺仪那样读到磁力计数据。
两种方式最终读取的都是同一套底层硬件。就指纹识别而言,重要的不是哪个 API 提供了这些数字——而是即便设备静止不动,这些数字里依然包含着什么。
校准噪声作为稳定的设备级 ID
把手机平放在桌面上,查询它的加速度计。理论上它应该报告 (0, 0, 9.8)——只有重力,别无其他。实际上它会报告类似 (0.013, -0.007, 9.79) 的数值:每个轴上都有微小的非零读数。这种偏差并非日常意义上的测量误差——它是加速度计的出厂校准值,而且相当一致。MEMS 加速度计和陀螺仪都是批量生产的,每颗芯片在制造过程中都会带上略有不同的偏移量和比例因子误差。关于基于传感器的设备指纹识别,学术研究已多次发现这个偏移向量确实携带可观的熵——足以帮助区分同一型号的不同个体,在综合多个轴、多个传感器的读数时尤其如此。
这正是校准噪声与 Canvas 或 WebGL 输出在本质上不同的地方。切换浏览器,或者 GPU 驱动改变了光栅化方式,Canvas 哈希值就会变化;安装一款新字体,字体列表也会随之改变。校准噪声不会因为这些而改变——它能在浏览器更新、恢复出厂设置乃至重装操作系统之后依然存在,甚至在同一部手机上把 Chrome 换成 Firefox 也不会改变,因为它是物理传感器芯片本身的属性,而不是任何脚本能够清除的软件状态。脚本只需捕获几秒钟"静止"状态下的读数,提取每个轴的平均偏移量,就能得到一个在设备整个使用寿命内都稳定不变的值。
权限管控——以及它管不到的地方
多年来,DeviceMotionEvent 和 DeviceOrientationEvent 触发时完全不需要任何权限提示——任何页面只需绑定一个监听器,就能在后台静默地开始读取校准噪声,用户毫无察觉。这一状况从 iOS 13 开始改变,苹果开始要求先显式调用 DeviceOrientationEvent.requestPermission()——该调用必须源自用户手势(如一次点击)——Safari 才会开始分发任何运动或方向事件。页面不能再仅靠加载就读取加速度计;它必须先询问,而用户必须先看到并同意一个系统对话框。
人们很容易假设其他引擎也跟进了。Chromium 并没有。这个细节值得说清楚,因为它关系到全球大多数手机。
Chromium 确实限制了谁能接触这些传感器。访问受 Permissions Policy 机制管控,accelerometer 与 gyroscope 的默认允许列表是 'self'——因此跨源的第三方 iframe 读不到它们——读取还要求安全(HTTPS)上下文,以及处于顶层且获得焦点的浏览上下文。但 Chromium 不会做的事,是询问用户。它自己的 Generic Sensor 设计文档把这个模型写得很直白:加速度计与陀螺仪是**"自动授予 + 允许退出"(auto-grant + opt-out)**。权限被直接授予,全程不会出现任何提示。
这也是为什么 accelerometer、gyroscope 和 magnetometer 会作为可查询项出现在更广泛的 Permissions API 指纹向量中——但一个名称可被查询,并不等于用户被询问过。
所以如实总结起来,这是一种分裂,而非一场干净的胜利:原始的校准信号在所有平台的硬件里都依然存在。在 iOS 上,脚本确实无法在用户点击"允许"之前采集到它。而在 Android 版 Chrome 上,一个普通的顶层 HTTPS 页面照样可以绑定 devicemotion 监听器,在毫无提示、毫无可见迹象的情况下读取校准噪声——和十年前几乎没有区别。iOS 关闭了这项技术的静默版本;Chromium 只是收窄了入口,却从未把这个决定交到用户面前。
为什么这是移动端专属向量
笔记本电脑或台式机内置加速度计和陀螺仪,通常只出于一个常见原因——某些机型的合盖检测或摇动检测功能——但绝大多数桌面硬件根本不配备这套传感器组件,DeviceMotionEvent 和 Generic Sensor 系列类在普通桌面浏览器上也就无从读取。手机和平板电脑则恰恰相反:运动与方向传感器几乎无处不在,因为操作系统本身就依赖它们来实现屏幕旋转、计步和增强现实等功能,所以这套硬件——以及暴露它的 API 层——在这一类设备上实际上是普遍存在的。
这也是这项技术能与更广泛的移动端指纹识别图景互补而非重复的原因:屏幕尺寸和设备像素比只能推断出你手里拿的大概是哪个型号,而传感器校准噪声——在仍可读取的地方——却能一路缩小到那一台具体的机器。正因为移动平台上的 GPU 与字体熵值早已被批量生产抹平,这种"精确到个体"的能力才显得格外有价值。它只是整体浏览器指纹识别图景中的一小块,但在移动端流量里,它是少数几个即便用户把设备上其他一切都重置了,依然能存活下来的信号之一。
缓解措施
- 保持操作系统与浏览器为最新版本。 iOS 的权限关卡是通过浏览器更新推送的,而不是一个可选的开关设置——过时的移动浏览器可能依然在不弹窗的情况下暴露运动数据。
- 拒绝你想不出明确用途的运动/方向权限请求——同时也要知道什么时候根本不会有提示。 在 iOS 上,一个既不是游戏、也不是 AR 功能或计步应用的页面却要请求加速度计权限,通常没有正当理由,而且拒绝确实有效。但在 Android 版 Chrome 上,往往根本不会弹出任何可供拒绝的提示,所以在那里,弹窗并不是一个你能依赖的控制手段。
- 在 Android 上,真正的抓手是你选择哪款浏览器。 既然 Chromium 是自动授予,有意义的缓解措施就不是权限提示,而是改用一款在策略层面限制或随机化传感器访问的浏览器——这与我们在隐私工具对比中介绍的是同一类防御思路。
- 把它当作众多信号中的一个来看待。 即便在可读取的情况下,校准噪声也只是更大指纹拼图中的一个轴,与屏幕参数、GPU 字符串和权限状态并列——没有哪个单一信号是追踪者的万能钥匙,也没有哪个单一措施能彻底消除指纹识别风险。
- 检查你自己的设备暴露了什么。 直接在你想评估的手机上运行 BrowserInsight 的指纹检测,查看浏览器目前暴露的实时信号集合。
常见问题
网站能在我不知情的情况下读取手机的加速度计吗?
这取决于你用的是什么手机。在 iOS 上不能——自 iOS 13 起,Safari 要求通过 DeviceOrientationEvent.requestPermission() 显式弹出权限提示,在你同意之前不会送达任何事件。而在 Android 版 Chrome 上通常可以:Chromium 把加速度计和陀螺仪视为自动授予,不弹出任何提示。它确实要求 HTTPS、顶层页面(不能是跨源 iframe)以及标签页处于焦点状态——但在这些限制之内,页面完全可以静默读取运动数据。
重置手机会改变它的传感器指纹吗?
不会。校准噪声来自加速度计和陀螺仪物理芯片的制造公差,而不是任何软件状态。恢复出厂设置、重装操作系统或更换浏览器,都不会改变底层硬件的偏移量。
桌面和笔记本浏览器也会暴露这个信号吗?
很少。大多数桌面和笔记本硬件根本不配备加速度计或陀螺仪,因此 DeviceMotionEvent 和 Generic Sensor API 系列类无从报告任何内容。这几乎完全是手机和平板电脑特有的信号。
传感器指纹识别比 Canvas 或 WebGL 指纹识别更具识别力吗?
单独来看并非如此——它是一个更窄、单一维度的信号。它对追踪者的价值在于异常稳定(能在重置和更换浏览器后存活),并且在移动设备上可用,而在移动设备上,字体和 Canvas 渲染等其他高熵桌面信号相对趋于扁平。
拒绝运动权限提示能完全保护我吗?
在你确实能看到提示的地方——也就是 iOS——拒绝对该来源是有效的:一个从未获得权限的页面将得不到任何运动或方向事件。但在 Chromium 上通常根本没有提示可供拒绝,所以在那里这并不是一个你能倚仗的控制手段。无论哪种情况,它都不影响其他被动信号,比如屏幕尺寸、GPU 渲染器字符串或权限状态,这些信号页面仍可在不弹窗的情况下读取。
结语
传感器指纹识别是一种狭窄但异常持久的信号:Canvas 哈希值或字体列表可能随软件更新而变化,而烙印在加速度计或陀螺仪芯片里的校准偏移量,却能在设备的整个使用寿命内保持不变。它也清楚地展示了移动端与桌面端指纹识别的真正分歧:一个在笔记本电脑上几乎不存在的信号,在手机上却近乎无处不在,恰恰是因为这套硬件本身在手机上是普遍存在的。
而权限这部分,恰恰是大多数总结讲错的地方。iOS 在 2019 年确实关闭了这项技术的静默版本,人们也很容易由此推广成"浏览器已经修好了这个问题"。但 Chromium 从未引入权限提示——它写在文档里的模型是自动授予加允许退出——所以在占据移动流量多数的 Android 上,顶层 HTTPS 页面今天读取校准噪声的自由度,和 iOS 13 之前相比几乎没有变化。无论在哪一边,底层的物理特性都没有改变——这正是为什么这条向量值得被单独理解,而不是简单地并入以桌面为中心的指纹识别手册。
推荐阅读:


