微信拦截了我的博客链接:验证文件放哪都是 404,最后一条 location 规则搞定

微信拦截了我的博客链接:验证文件放哪都是 404,最后一条 location 规则搞定

架构:1Panel + OpenResty 反向代理 + Halo(Docker) 起因:把博客文章发给好友,微信提示「已停止访问该网页」 结果:域名归属验证通过当天,链接申诉即受理并临时恢复访问(本文时间点:2026-10-29,含后续更新)

我把刚写好的《共享文件夹权限申请(OA 5102)操作手册与排错指南》发给好友,结果对方点不开——微信提示:

微信「已停止访问该网页」拦截页

「网页包含游戏、互动测试内容,被多人投诉」——我那篇文章里连个 emoji 都没有,这理由看着就很模板化。但没关系,微信给了申诉入口:点「申请恢复访问」,我是站长,选择第一个选项,然后微信要求先完成域名归属验证。

要求很简单:在网站根目录创建一个 TXT 文件,以指定哈希命名,内容为另一串哈希,并保证这个 URL 能访问到该内容。

微信部署验证文件要求:文件名与内容都是哈希

文件名:444635ffb693a1781766f4b4e67fe50c.txt
内容:  eb28f1f566a2a275d77d8e2e15196a822eb43ffc
要求:  https://你的域名/444635ffb693a1781766f4b4e67fe50c.txt 能返回这串内容

听起来 5 分钟就能搞定的事,我折腾了半天。


第一波尝试:放哪都是 404

我的站点是 1Panel + OpenResty 反向代理 + Halo(Docker),站点类型是"反向代理"。按照"网站根目录放个文件"的惯性思维,我依次试了三个地方:

尝试 位置 结果
① Halo 工作目录 /opt/1panel/apps/halo/halo/data/ ❌ 404
② Halo 官方文档说的静态目录 data/static/(手动新建) ❌ 404
③ 1Panel 站点根目录 /opt/1panel/www/sites/note/index/ ❌ 404

文件确实放在那里了,权限 755,内容一字不差:

尝试一:放进 Halo 工作目录 data/

尝试二:放进 Halo 官方静态目录 data/static/

三种姿势全灭。为什么?

原因:反向代理下,磁盘上的文件根本"轮不到"被读取

冷静下来看一眼反代站点的 Nginx 配置,答案就写在最后一行:

include /www/sites/note/proxy/*.conf;

这个 include 引入的正是反向代理规则,里面通常有一条:

location / {
    proxy_pass http://127.0.0.1:端口;
}

它的含义是:所有请求,全部转发给 Halo 容器处理。

也就是说:

  • 请求到达 OpenResty 后,被 location / 匹配,原封不动转发给 Halo;
  • Halo 在自己的世界里找这个 txt 文件,当然找不到,返回 404;
  • 磁盘上不管你把文件放在 index/、data/ 还是 data/static/,Nginx 根本没有机会去读它。

「网站根目录放个文件」这个方案,只对静态站点(Nginx 直接 root 指向目录)有效。反代架构下,这条路从方向上就是错的。

至于 Halo 的 static 目录映射,思路没错,但要求请求先能到达 Halo、且 Halo 正常做了容器内外路径映射,再加上权限等因素,链路太长,不如直接从 Nginx 层解决。

正确姿势:让 Nginx 直接把内容"说"出去

既然文件读不到,那就干脆不用文件。

Nginx 的 location = 是精确匹配,优先级高于 location /。加一条规则,让 Nginx 遇到这个 URL 时直接返回固定内容——请求根本不会落到磁盘,更不会转发给 Halo:

location = /444635ffb693a1781766f4b4e67fe50c.txt {
    default_type text/plain;
    return 200 'eb28f1f566a2a275d77d8e2e15196a822eb43ffc';
}

实际配置长这样:

1Panel 站点配置文件中添加 location = 精确匹配规则

在 1Panel 中的操作路径:网站 → 对应站点 → 配置文件,把这段加进 server {} 块内(放在 include ... proxy/*.conf; 前后均可,精确匹配天然优先),保存后 OpenResty 会自动 reload。

⚠️ 单引号里的内容必须和微信给的一字不差,开头结尾不要多空格或换行——哈希校验是全串比对的。

验证

保存配置后先用 curl 自测:

curl https://note.huazhuhui.fun/444635ffb693a1781766f4b4e67fe50c.txt

输出那串哈希即成功。然后回到微信的验证页面点提交(提交前别关闭页面)。

我是发布完才写的这篇文章,刚才又实测了一遍,规则至今还在正常工作:

$ curl -s https://note.huazhuhui.fun/444635ffb693a1781766f4b4e67fe50c.txt
eb28f1f566a2a275d77d8e2e15196a822eb43ffc        # 200 text/plain

微信的域名归属验证当场通过。


然而:验证通过了,好友还是打不开

这是我这次踩坑里最值得记录的一课。

域名归属验证通过后,我自己访问那篇文章是正常的,但好友在微信里打开,仍然提示已停止访问。

也就是说,「部署验证文件」和「链接解封」是两件事:

  • 验证文件:向微信证明这个域名是你的——技术动作,秒过;
  • 链接解封:微信人工/系统审核这个链接的内容是否合规——流程动作,要等。

验证通过只是拿到了申诉资格,接下来要把申诉本身走完。微信的申诉表单长这样:

微信链接申诉表单:违规链接、申诉理由、网站核心功能链接

要填的字段:

  • 违规链接:被拦截的完整 URL
  • 申诉理由:10–200 字,说明网站类型和被误报的情况
  • 网站核心功能链接(选填):能体现站点性质的链接
  • 相关证明图片(选填):最多 4 张

如果分享到朋友圈后仅自己可见

微信官方给出的处理路径有三条:

  1. 若域名未在工信部 ICP 备案,分享频率会受到限制,请先完成备案;
  2. 根据《微信外部链接内容管理规范》检查该页面所用域名、IP 下是否存在违规内容,若有请修改;
  3. 确认不存在违规内容后,可发邮件到腾讯指定邮箱 moment@tencent.com 反馈。

邮件标题格式:【链接解封反馈】+「反馈人或企业」+「页面主题」 正文附上仅自己可见的链接以及情况说明。

申诉小贴士

  • 申诉理由写清"个人非经营性博客、文章为原创技术分享、无广告引流及违规内容",100~150 字为宜;
  • 核心功能链接填博客首页或归档页,比单篇文章更能体现站点性质;
  • 证明图片上传首页截图、被拦截文章正文截图,如有 ICP 备案一并附上,通过率会高很多;
  • 官方口径一般 1~3 个工作日出结果,期间不要重复提交。

后续:申诉受理,当天临时恢复访问

更新于 2026-10-29 晚。

申诉表单提交后没多久,微信就发来了「申诉受理通知」:

微信申诉受理通知:申诉已受理,临时恢复访问

链接【https://note.huazhuhui.fun/archives/oa5102-share-folder-permission-guide#_1】的申诉已受理。 目前已为你临时恢复访问,请注意辨别,保护个人隐私和财产安全。

两点实测结论:

  1. 表单申诉很快。 官方口径是 1~3 个工作日,实际当天就受理并临时恢复访问——上文"验证通过后好友还是打不开"的状态,到当晚就解除了。所以如果你的站点内容确实没问题,别被"1~3 个工作日"吓住,先把表单走了再说。
  2. 措辞是「临时」恢复访问。 通知里没有说"已解封",而是"临时恢复"+ 一句"请注意辨别,保护个人隐私和财产安全"——可以理解为还处在观察期。后续保持内容干净就好。

两条申诉通道的速度对比:表单(weixin110.qq.com)当天受理;而针对朋友圈仅自己可见场景的 moment@tencent.com 邮件申诉,我已经发出,还在等回复——两条通道走的是不同流程,速度差得非常明显。如果只是链接被拦,优先走表单;邮件留给朋友圈限流那种表单处理不了的场景。


举一反三:这个技巧可以复用

location = + return 200 是验证类需求的通用解法,以下场景全部适用:

  • 百度站长平台文件验证
  • Google Search Console HTML 文件验证
  • Bing Webmaster 验证
  • 各种 App / 开发者平台要求的域名归属校验

以后再遇到"在网站根目录放 xxx.txt",反代架构下直接加一条 location 规则:

location = /baidu_verify_xxxx.html {
    default_type text/html;
    return 200 '验证内容';
}

不用碰文件系统,不用关心 Halo 的目录结构,也不用重启容器。


总结

架构 验证文件放哪
静态站点(Nginx root 指向目录) 文件放根目录即可
反向代理站点(本文场景) location = 精确匹配 + return 200,跳过文件

另外记住两件事:

  1. 域名归属验证 ≠ 链接解封。前者是技术动作(秒过),后者是审核流程(要等)。验证通过后好友还是打不开,不代表你做错了,是流程还没走完。
  2. 先查服务端再怀疑客户端。被拦截的文章用浏览器直接访问是 200 的,问题只出在微信的拦截层——分清楚"哪一层坏了",排查方向才不会乱。

一句话:反代架构下,"网站根目录"是个伪概念——根目录不在磁盘上,而在 Nginx 的配置里。


本文时间线(均在 2026-10-29 当天):链接被拦截 → 完成域名归属验证(curl 实测 200)→ 表单提交申诉 → 当天收到「申诉受理通知」,临时恢复访问 → 邮件申诉(moment@tencent.com,朋友圈场景)已发出,等待回复。文中的验证文件路径、Nginx 配置、申诉表单字段均来自实际操作截图。