把阅后即焚链接贴进会生成预览的聊天之后,阅读次数为什么不一定已经被用掉
频道里先跳出一张卡片,不等于接收方已经读过密文。聊天软件为了生成预览,会向页面发一次 HTTP GET;这次抓取通常只读标题和摘要,不会点「打开并查看」,也不会带走地址栏 # 后面的密钥。下面把「生成卡片」和「消耗一次阅读」拆开,并写出当场能对照的步骤。不是阅后即焚创建页的操作说明书。
先分清 卡片抓的是哪一层
本篇只回答「贴进会生成预览的聊天之后,阅读次数为什么不一定已经被用掉」。不是阅后即焚的表单说明,也不是「# 为什么不进服务器日志」那一层。
预览卡片抓的是 哪一层
卡片出现在你按下发送的前后几秒。动作来自聊天软件的服务器,不是接收方的手指。
把一条 https://…/s.html?id=…#… 贴进 Slack、Discord、企业微信或微信之后,输入框或消息下方常常先跳出一张小卡片:标题、一两句摘要、有时还有图标。很多人把这张卡片读成「链接已经被打开过了」。顺序其实相反。聊天软件要先向这个地址发一次 HTTP GET,从返回的 HTML 里抽出 og:title、og:description 或普通 <title>,再画卡片。接收方此时可能还没点进去。
Slack 把这件事写进了官方说明。默认情况下,用户和 Slack 应用发出的、带完整网址的消息都会展开链接;媒体内容也可以展开。说明见 Slack 文档《Unfurling links in messages》。专门负责展开链接的机器人自称 Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots)。同一页 Slack Robots 写明:它会尽量少取页面(使用 HTTP Range),目标是 oEmbed、Twitter Card 和 Open Graph 标签;如果标签指向图片、视频或音频,才会再取那份文件做校验。响应大约缓存 30 分钟。文档没有写「执行页面上的 JavaScript」或「替用户点按钮」。
浏览器发出这次 GET 时,# 后面的内容不会进入请求行。IETF RFC 3986 §3.5 把 fragment 定义成客户端标识,不参与服务器对 URI 的处理。所以预览机器人即便完整复制了你在聊天框里看到的字符串,真正打到 UsePwd 的请求通常只到 s.html?id={编号}。密钥为什么不进访问日志,见已有文章URL 的 # 片段为什么不会出现在服务器日志里。本篇要补的是另一层:这次不带密钥的 GET,算不算「读过一次」。
预览要问的不是「聊天软件有没有看见这串网址」,而是「这一次 GET 有没有走到取密文的接口」。卡片画出来,只证明标题被读过;密文还在不在,要另查。
第一次 GET 为什么 不等于读过
若工具把「谁来取密文」和「谁来打开落地页」绑成同一次请求,预览机器人就会把唯一的一次阅读用掉。分层之后,这两步不再是同一个动作。
不少一次性链接把密文直接挂在被预览的那个 URL 上:机器人 GET 一次,服务器就返回正文并删除记录。接收方随后点开,看到的是「已被阅读」或 404。这个失败很常见,原因不是 Slack「恶意烧掉秘密」,而是实现把 RFC 里本该安全、可缓存的 GET,当成了「销毁密文」的动作。
UsePwd 的阅后即焚把三步拆开。创建时,当前标签页用 Web Crypto 按 AES-256-GCM 加密,明文上限 32 KB;上传字段只有密文、过期时间和阅读次数。过期时间可选 1 小时、24 小时、7 天,或「仅阅后焚毁」;阅读次数 1–10,默认 1。链接形态是 s.html?id={id}#{key}。创建页和阅读页都打开即用,双方都不用注册。服务器只暂存密文,看不到明文,也没有账号可以按用户找回。
接收方打开阅读页时,页面先向 /api/secrets/{id}/status 询问密文还在不在。这一步只返回 active、burned 或 expired,不增加阅读计数,也不删除记录。只有点了「打开并查看」,浏览器才会请求 /api/secrets/{id} 取回密文,并在本机用 # 后的密钥解密。达到创建时设定的次数后,服务器删除密文;再取会得到 410。预览机器人停在落地页 HTML,常见情况下既没有密钥,也不会去点那个按钮。
返回静态阅读页。标题是「打开阅后即焚链接」,不含明文。预览卡片通常停在这一层。
只回答还在、已焚毁或已过期。反复查询也不会把次数加一。
这才计入一次阅读。默认 1 次后删除密文。阅读页上对应「打开并查看」。
阅读页还写了一句可以当场核对的提示:点按钮「可能消耗一次阅读次数」。没有脚本就无法解密,页面用 <noscript> 说明了这一点。预览机器人若只读 HTML、不执行脚本,连状态查询都不会发出;即便某家内置浏览器执行了脚本,也只先走到「密文还在」,仍要等人点按钮。
哪些机器人会来、拿走什么
能画卡片的软件很多。它们拿走的是页面抬头,不是 # 后面那串密钥,更不是解密后的明文。
Slack 的链接展开机器人、Discord 用来生成嵌入卡片的抓取、微信和企业微信里把网址收成一张卡片的服务端请求,都属于同一类:先 GET 页面,再从 HTML 里找标题和摘要。Slack 另外说明,它不把 robots.txt 当成传统爬虫规则来遵守,因为展开链接是「替发链接的人办事」,不是顺着站点乱爬。你在阅读页加 noindex,挡得住搜索引擎收录,挡不住频道里的那张卡片。
UsePwd 的阅读页本身是临时密文场景,带 noindex, nofollow,也不进站点地图。页面标题固定写成「打开阅后即焚链接」,描述只说明解密在当前标签页完成、密钥在 # 后面。预览卡片若成功生成,频道里看到的就是这句通用说明,不会出现你写入的密码、Token 或工单原文。这和「服务器日志里有没有密钥」是两件能同时成立的事:卡片证明有人 GET 过落地页;日志里仍然没有 fragment。
Slack 写过,同一 URL 的展开结果大约缓存 30 分钟。短时间里把同一条测试链接反复贴进频道,不一定会看到第二次抓取。要核对「机器人来过没有」,应看你自己的访问日志里有没有 Slackbot-LinkExpanding 这类 User-Agent,而不是盯着卡片刷新几次。日志里出现对 s.html 的 GET,仍然不能推论「/api/secrets/{id} 已被调用」。
什么情况下次数 真的会被用掉
「不一定用掉」不是「永远用不掉」。能点到「打开并查看」的访问,才会走进取密文那一层。
最常见的消耗者是接收方本人:打开完整链接,看到「密文还在」,再点「打开并查看」。默认次数是 1。这一次成功之后,服务器删除密文;同一条链接再打开会提示已被焚毁。若创建时把次数设到 2 或更高,前几次取回后密文仍在,直到计数达到上限。过期时间到了也会删除:默认 24 小时,也可以是 1 小时、7 天;选「仅阅后焚毁」则只按次数删,不按钟点删。
第二类是会执行脚本并且模拟点击的环境。部分邮件安全网关、链接沙箱会在隔离浏览器里打开网址,有的还会点页面上的主按钮。那已经不是「生成一张卡片」,而是另一次完整的、像人一样的访问。若沙箱点了「打开并查看」,次数会被用掉,接收方随后看到焚毁态。这一层要用网关自己的报告核对,不能从聊天卡片反推。
第三类是把取密文的接口地址直接发出去。阅读页地址是 s.html?id=;真正消耗次数的是 /api/secrets/{id}。普通用户不会复制后一条。若有人把接口 URL 贴进会预览的频道,而那家工具又把第一次 GET 当成取密文,次数会在预览阶段被用掉。UsePwd 的分享形态不走这条地址,创建页复制的是带 # 的阅读页链接。
预览没烧掉次数,不等于秘密只存在于接收方那里。聊天软件仍保存完整网址,工作区管理员还可能导出记录。次数限制的是服务器上密文的寿命,不是频道里那串地址还能被谁打开。
当场怎么 核对照预览
目标不是证明「全世界的聊天软件都不会读密文」,而是证明:卡片出现之后,取密文的接口还没有被调用。
-
01
准备一条不会用于真实交接的测试内容
不要写入正在使用的 API Key 或登录密码。例如打开阅后即焚,输入
PreviewCard-20260905,次数保持默认 1,过期保持 24 小时。页面打开即用。下面的步骤只为对照预览和接口,不把这段字交给同事当正式密钥。 -
02
记下完整链接,先自己打开阅读页
生成后应看到
s.html?id=和#两段。用同一条链接在当前浏览器打开。页面应停在「密文还在」,并出现「打开并查看」。先不要点按钮。按 F12 打开网络面板,应能看到对/api/secrets/{id}/status的请求;此时不应出现对/api/secrets/{id}且无/status后缀的取密文请求。 -
03
把同一条链接贴进会生成预览的测试频道
用一个只有你自己的 Slack 频道、Discord 私信或测试群。贴出后等卡片出现。卡片标题应接近「打开阅后即焚链接」,不应出现
PreviewCard-20260905。回到阅读页刷新,或换一个未点过按钮的窗口再打开同一链接,应仍停在「密文还在」。若这里已经变成「已被焚毁」,说明有别的访问走到了取密文接口,而不是「卡片本身等于阅读」。 -
04
需要时再对照访问日志里的 User-Agent
若你能看到站点访问日志,预览阶段常见的是对
/cn/s.html?id=…的 GET,User-Agent 可能含Slackbot-LinkExpanding。同一时间不应出现对/api/secrets/{id}的成功取回。Slack 对同一 URL 大约缓存 30 分钟,短时间重复粘贴不一定产生第二次抓取。 -
05
最后才点「打开并查看」,确认次数被用掉
现在点按钮。网络面板应出现取密文的请求,页面展示测试原文。关闭后再打开同一链接,应提示已被焚毁。这一步用来对照「按钮之后」和「卡片之后」不是同一状态。测完即可丢掉这条链接,不要把它改派给真实接收方。
若你只是要把新密钥交给另一个人,不要先把明文贴进频道「试一张卡片」。测试内容和正式内容分开。正式交接仍然走阅后即焚;环境变量泄露后的第二轮风险,见云平台环境变量被拖走之后,新密钥为什么不该再发到聊天窗口。那篇写的是「不要把 API Key 本身贴进可搜索的记录」;本篇写的是「链接贴进去之后,预览抓取停在哪一层」。
次数没掉,聊天里还 留下什么
把「卡片没有烧掉密文」读成「这条链接已经从频道里消失」,会漏掉几条同样能核对的边界。
聊天软件保存的是你贴出去的整串地址。谁能搜索历史、导出工作区、打开备份,谁就能再次打开阅读页。次数还在时,后打开的人仍可能点「打开并查看」并读到明文;次数用尽后,记录里留下的是一条已焚毁的链接,加上当时的卡片标题。管理员导出改不了服务器上已经删除的密文,但改不掉「当时频道里出现过完整网址」这件事。
截图和转发是另一份副本。有人把阅读成功后的明文截下来,或把链接转到另一个会预览的群,边界就从「这一次 GET」变成「下一跳还经过谁」。阅后即焚限制服务器上密文的寿命和次数,不限制接收方是否截图。UsePwd 没有账号和密码库,也不能按用户找回丢失的链接。需要长期保存或多设备同步时,应使用专门的密码管理器。身份说明见关于。
文件是第三条路径。单文件不超过 5 GB 的本地备份,走文件加密盒,输出 .lock / .enc,文件默认不上传。口令本身用密码生成器在 6–128 位之间生成,再用密码检测看强度。这些页面和本篇一样打开即用。不要把「预览没烧掉次数」理解成「贴进任意频道都安全」:频道记录和预览抓取不是同一层。
预览之后 常被问到的
下面四条只回答本篇的边界,不重复创建页上的按钮说明。
读完去 核对照一张预览卡片
文章回答「预览之后次数为什么不一定已经被用掉」。要当场生成一条不用于真实交接的测试链接再贴进测试频道,打开阅后即焚即可,不必先注册。