URL 的 # 片段为什么不会出现在服务器日志里
浏览器发出 HTTP 请求时,# 后面的内容留在本地。阅后即焚把解密密钥接在 s.html?id={id}#{key} 的 # 之后:服务器只收到密文编号,看不到密钥。阅读页对接收方公开,不必先注册。下面把这条边界拆开,并写出当场核对的步骤。
# 后面 扮演什么
秘密出现在地址栏,不等于服务器日志里一定有一份拷贝。这个判断对查询参数大体成立,对片段不成立。
运维把临时口令塞进聊天软件、客服把后台地址连同 token 一起转发时,最怕的往往不是「对方看得到」,而是「中间每一跳都可能留下一份完整链接」。很多人因此默认:只要秘密出现在地址栏,服务器日志就一定有一份拷贝。
一段完整地址可以拆成三块。协议和主机决定浏览器连谁;路径和问号后面的查询参数决定要哪份资源,这两块会出现在 HTTP 请求行里。井号之后的字符叫 fragment,中文常译作片段。它最初用来告诉浏览器滚到页面上的某个锚点,后来前端脚本也用 location.hash 在本机读这段文字。服务器既收不到它,也不该拿它做路由或鉴权。
把密钥放在 # 后面,并不是又发明了一种加密算法。它只是利用浏览器长期遵守的发送边界:同一条链接可以同时携带「给服务器的编号」和「只给当前标签页的密钥」。UsePwd 阅后即焚用的就是这个边界。创建页和阅读页都打开即用,双方都不用注册;服务器只暂存密文,明文和密钥默认不作为请求正文发出。
真正发出去的是 哪一段
看 s.html?id=abc123#the-key。浏览器发出的 GET,请求行通常只有路径和 id。#the-key 不在请求里,也没有日志可记。
这是 URL 标准长期如此,不是某一家站点的私有约定,更不是「服务器答应不看」。表里的「服务器能不能看到」指的是:在 TLS 终止之后,源站或你自己控制的反向代理,能不能从这次 HTTP 请求里读到该字段。它不讨论本机已被控制、扩展能读页面,或对方截图另存的情况。
?id=abc123&key=secret
整段出现在请求行。常见访问日志通常会留下完整 URL。
#secret
浏览器不把它当作请求的一部分。常见访问日志没有这一段可记。
ciphertext
创建阅后即焚时实际上传的部分。UsePwd 这里只有密文、有效小时数和阅读次数。
一个常见误区是:「已经用了 HTTPS,日志就看不见。」传输加密保护的是线路上的内容不被中间人读到明文。源站和你自己控制的反向代理,在 TLS 终止之后,仍然能看到完整的请求行。所以 HTTPS 并不能把 ?key= 从访问日志里抹掉。片段之所以不进日志,是因为它根本没被发出去,不是因为线路被加密了。
另一个容易忽略的通道是 Referer。默认情况下,有些跳转会把「来源页的 URL」带给下一站。现代浏览器在 HTTPS 之间跳转时,默认策略通常会去掉 fragment;查询参数却仍可能出现在 Referer 里。这也是一次性密钥更适合放在 # 后、而不是 ?key= 的原因之一:你没法要求每一个下游站点都承诺不记来源地址。
片段不进 HTTP,不等于「链接本身不能被复制」。地址栏里的完整字符串,包括 # 后面的密钥,仍然会出现在本机历史、分享预览和你亲手发出的消息里。本文只解释服务器日志这一层,不把片段写成万能保险箱。
打开网络面板 就能看见
目标不是证明「全世界都看不到」,而是证明:这次发给 UsePwd 的 HTTP 请求里,没有 # 后面的密钥。
-
01
打开阅后即焚创建页
进入阅后即焚。页面打开即可用,不必登录。输入一段你认得出来、但不要用真实生产密钥的示例文字。
-
02
打开网络面板并清空记录
按 F12 或右键选择检查,切到网络(Network)。必要时清空已有请求,避免和页面首次加载混在一起。
-
03
创建一条链接
提交后,浏览器会先在当前标签页用 AES-256-GCM 加密,再向
/api/secrets发送请求。字段是ciphertext、ttl_hours、max_reads。生成的分享地址形态是s.html?id={id}#{key}。 -
04
检查创建请求
点开那条 POST。请求 URL 里不应出现
#后面的密钥;请求正文里应是密文和两个数字,不是你刚输入的那段示例文字。 -
05
再打开阅读页核对 GET
用同一条链接打开阅读页。随后的 GET 或状态查询,路径里只有
id。把地址栏里#后的字符串,和网络面板里的请求 URL 并排对照:前者在本地,后者没有这一段。
生产环境可能还有发往 /tj/ 的访问分析。载荷是页面与按钮名,例如「创建链接」,不是明文、不是密钥、也不是文件内容。本机预览不会发送分析。若你只关心「密钥有没有进 HTTP」,先过滤出 /api/secrets 即可,不必把分析请求误当成密文通道。
这组步骤和安全说明里「明文会不会离开浏览器」是互补的:安全说明回答本机计算的范围,本文只把 URL 拆开,说明为什么日志里没有 # 那一段。两页都不代替创建页上的操作表单。
阅后即焚怎样 利用 这条边界
编号走查询参数,密钥走片段。服务器只知道有一份密文、能读几次、何时过期,不知道用什么解开。
创建时,当前标签页用 Web Crypto 生成随机密钥,按 AES-256-GCM 加密文本,再把密文交给服务器。返回的编号写进 ?id=;密钥只接在 # 后面。
阅读页对接收方公开。对方打开 s.html?id={id}#{key} 时,浏览器先用 id 向服务器取密文或询问状态,再用本机保存的片段密钥解密。达到创建时设定的次数后,服务器删除密文,链接无法再读。接收方同样不用注册。阅读页本身是临时密文场景,不作为本站的收录入口;要理解产品能力,应回到创建页或本篇的核对步骤。
把密钥放在片段里,解决的是「服务器日志和请求行」这一层。它不解决「你把完整链接发给了谁」。聊天软件、邮件、工单系统都会保存你粘贴的整串地址。谁拿到完整链接,谁就同时拿到编号和密钥。阅后即焚限制的是服务器侧的密文寿命和阅读次数,不是接收方是否截图、是否转发。
和查询参数方案差在哪
有些一次性链接把解密材料写成 ?k=。实现简单,但每次打开都会把密钥写进请求行,CDN、WAF 和源站访问日志都能留下一份。片段方案多写一个井号,换来的是:托管侧即使完整记录 URL,也缺解开密文的那一半。代价是你必须提醒接收方复制完整链接,不要只复制问号前面的部分;缺了 # 之后,阅读页只能取到密文,无法在本机解开。
这也是为什么本文不把阅后即焚写成「密码管理器」或「可以找回的保险箱」。UsePwd 没有账号,没有密码库,也不能按用户找回口令。链接丢了、片段被截断、次数用尽,服务器都无法替你还原明文。身份说明见关于。
不要把片段密钥理解成「只有受信服务器能解密」。事实正好相反:服务器没有这段密钥,也无法代为解密。能解密的是任何打开完整链接的浏览器标签页。信任边界在「谁拿到整串地址」,不在「哪一台服务器更可靠」。
片段 挡不住 的几件事
把「不进服务器日志」读成「绝对安全」,会漏掉几条同样能核对的边界。先列出来,避免把一篇原理文当成保证书。
# 之前的 URL,但你发给真人的消息里仍有完整密钥。
适合阅后即焚的,是你信任发送通道、看完即止的一次性交接:临时口令、一次性 API Key、短时验证码。不适合当长期保险柜,也不适合代替面对面交付高价值主密钥。
文件备份是另一条路径。单文件不超过 5 GB 的本地加解密,走文件加密盒:AES-256-GCM 在当前标签页完成,输出 .lock / .enc,文件默认不上传。那是「自己留一份密文文件」,不是「把密钥塞进 URL」。两条工具不要混用成同一种保证。
交接时怎么 选通道
你必须把一段短秘密交给另一个人,又不希望托管侧的访问日志留下能解开它的材料。按下面的顺序判断,而不是先问哪家站点口号更响。
若秘密只需要被读有限次数,并且双方都能打开浏览器,用阅后即焚:明文在本机加密,编号走 ?id=,密钥走 #,打开即用。创建之后用网络面板对照一次,确认 POST 正文是密文、GET 的 URL 没有片段。若你其实需要长期保存、多设备同步或找回,那已经超出本站能力,请使用专门的密码管理器,不要把 UsePwd 理解成账号系统。
若秘密根本不该进任何第三方页面,就不要生成链接:当面口述、离线介质,或只在双方已有的端到端通道里传。片段方案减少的是「服务器日志里的密钥」,不是「世界上所有能看见屏幕的人」。能分清这两层,才不会把一篇 URL 原理文读成产品担保。
密码本身强不强,是另一件事。生成 6–128 位随机口令用密码生成器;要在本机看强度并对照随页面提供的公开泄露弱口令名单,用密码检测。检测不是全网撞库,待测口令不会上传。外发链接或工单正文前,用隐私清洗去掉跟踪参数或做脱敏。这些页面和本篇一样打开即用,顶栏右侧只有语言切换。
读完去 当场核对
文章回答「为什么日志里没有 # 后面那一段」。要生成一条可焚毁的加密链接,打开阅后即焚即可,不必先注册。