你刚复制了一个密码,切到某个网站,就看到它请求读取剪贴板。点下“允许”,究竟会交出去什么?如果始终没有弹出提示,是不是就说明页面什么也读不到?
这里有两条途径。往页面里粘贴,会把这次粘贴所涉及的数据交给页面。浏览器还提供了另一套 API,允许页面在符合访问规则时,不经粘贴就读取剪贴板。把这两件事混为一谈,就会得出两种错误答案:令人安心的“网站读不到你的剪贴板”,以及令人紧张的“每个打开的标签页都看得到你的密码”。
粘贴这一步,已经把数据交了出去
在文本框里按下 Ctrl+V 或 Command+V,浏览器就会触发 paste 事件。监听器可以在文字出现在框里之前,调用 event.clipboardData.getData('text/plain') 读到它。对于这种由用户主动发起的粘贴,不需要再弹一次剪贴板权限对话框。你刚刚已经告诉浏览器,该把数据放到哪里。
这个事件会沿文档向上冒泡,所以监听器不必装在那个文本框上。页面还可以取消默认的文字插入行为。粘贴之后框里仍然空着,并不能证明页面什么也没收到。
在这里试一下。选中并复制示例文字,再粘贴到空白框里。演示会统计文字长度,并列出事件提供的数据格式。它会丢弃粘贴的文字,不把文字插进框里。这两个测试中的任何内容,都不会被这个组件上传或保存。
请使用这段无害的示例文字。自己选中并复制,然后分别尝试下面两种方式。复制会替换剪贴板当前的内容。
bscan clipboard sample 123 你把内容粘贴到页面
页面请求读取内容
这个按钮会请求剪贴板当前的文字。使用前,请只复制上面的示例。浏览器可能会请求授权,或显示一个粘贴菜单。
一个电子表格单元格或一段带格式的文字,可能不只提供纯文本。剪贴板可以同时保存同一份内容的多种表示形式,比如 text/plain 和 text/html。页面能收到浏览器为这次粘贴提供的格式,不仅仅是你以为会出现在框里的那些字符。本演示只列出格式名称,不会渲染粘贴的 HTML,也不会打开粘贴的文件。
不粘贴,网站也能读取剪贴板吗?
能,前提是浏览器允许直接读取。navigator.clipboard.readText() 会请求读取剪贴板当前的文字。read() 还可以请求浏览器支持的非文本格式。这些方法属于 Async Clipboard API(异步剪贴板 API),只能在 HTTPS 等安全上下文中使用。安全连接是前提条件,并不等于网站可以随意收集你的数据。
先复制无害的示例文字,再点演示中的读取按钮。这会发出真正的 API 请求,因此浏览器可能会显示自己的权限提示或“粘贴”界面。页面会显示请求是否成功,以及返回的文字有多长。读取被拒绝后,它不会亮起一个绿色的“浏览器安全”徽章:拒绝只说明,在当前焦点状态和权限设置下,这一次请求没有成功。
剪贴板规范明确区分了用户真正执行的粘贴,以及脚本派发的一个名为 `paste` 的事件。脚本不能伪造受信任的粘贴事件,借此取得系统剪贴板的访问权限。所以,第一个测试需要你亲自粘贴,第二个则需要浏览器批准读取。Chrome 可以记住授权,Safari 和 Firefox 则不同
在 Chrome、Edge 等 Chromium 浏览器中,获得焦点的文档可以请求 clipboard-read 权限。如果这项权限已经获准,符合条件的读取请求就可能直接成功,不再弹出提示。“这一次没问我”,并不能证明你从未授权。请检查这个网站现有的权限。
Firefox 和 Safari 没有实现同样的持久 clipboard-read 权限。它们的直接读取流程要求近期发生过用户交互,并且可能显示一个临时的“粘贴”选项。如果读取的内容是从同源页面复制的,这个提示可能不会出现。因此,只用测试页面自己提供的文字来测试,容易让你误判:从其他应用复制文字时,结果未必一样。
第二轮可以这样试:在本地文本编辑器中随便写一句不含敏感信息的话,从那里复制,再回到这里请求读取。比较浏览器弹出的界面,而不只是最后的数字。MDN 记录了这些浏览器差异;WebKit 也解释了自己的剪贴板访问设计。嵌入的 iframe 和浏览器策略还可能施加额外限制,所以请用你实际使用的浏览器测试。
点“复制”按钮,会读到剪贴板原来的内容吗?
不一定会。使用 navigator.clipboard.writeText() 的按钮,会把页面提供的文字写入剪贴板。这个方法不会先返回原来的内容。读取和写入是两种独立操作,访问规则也不同,Google 的异步剪贴板指南对此有详细说明。
页面也可以处理 copy 事件,自行决定放进剪贴板的内容,并取消默认复制行为。copy 事件 API 不会把剪贴板原有的内容交给处理函数。但页面可以读取你在它自己的文档中选中的文字。从网页上复制一句话,本身就是页面能观察到的操作,我们的另一篇切屏与页面活动演示展示了这一点。
这也解释了为什么网站有一个“复制”按钮,并不代表复制出来的文字就和屏幕上显示的一样。粘贴命令后,先检查再运行。危险发生在你执行了收到的内容那一刻,不是因为页面上有个“复制”按钮。
网站能看到你的剪贴板历史记录吗?
普通网页使用的 Clipboard API,没有列出操作系统剪贴板历史记录的方法。获准读取,读到的是剪贴板当前的内容,并不是一份能搜索你上周所有复制操作的档案。剪贴板管理器、浏览器扩展和原生应用各有自己的访问机制,不能拿某个手机应用的行为,来证明普通网页也能做到同样的事。
但这个限制不会抹掉你已经交出去的数据。网站收到文字后,可以保留一份自己的副本。之后替换剪贴板内容、关闭标签页或重置权限,都不能收回那份副本。同样,上面的“清除结果”按钮只会清空这个演示的显示结果,不会清空系统剪贴板,也不会撤销浏览器权限。
关掉你实际打开的那条访问途径
在桌面版 Chrome 中,依次打开“设置”“隐私和安全”“网站设置”,再找到“剪贴板”。检查允许访问的网站,移除不再需要的授权。你也可以点地址栏旁当前网站的控制入口,查看它的网站设置。Google 的权限指南介绍了这些设置。即使禁止直接读取,页面仍然可以收到你主动粘贴给它的内容。
日常使用时,只往你确实打算交出数据的地方粘贴。检查权限时,用不含敏感信息的示例。如果你想知道页面在你没有交互时能获取什么,可以对照看看字体指纹或 WebGL 渲染器信息:它们走的是其他数据采集途径,剪贴板读取被拒绝,并不能说明这些途径的情况。
如果你用独立的浏览器配置文件管理客户账号,Incogniton 这类工具可以帮你整理这些工作。但每次粘贴,仍然是在主动把数据交给接收它的页面。配置文件彼此隔离,也不是把客户机密粘贴到错误账号里的理由。
复制示例文字,对比两项测试的结果,再检查测试过程中授予了哪些权限。接下来运行完整扫描,看看那些不依赖粘贴也能获取的浏览器信号。