Skip to content

校验文件上传页面与服务部署 ​

使用方式 ​

网站首页提供“上传业务域名校验文件”入口,独立地址为 /admin/verification。输入管理员上传密钥,将微信小程序业务域名配置时下载的原始 .txt 文件拖入页面(也可以点击选择),再点击上传。

文件按原名和原始字节写入服务器 deployRoot/shared/,同名普通文件直接覆盖。若同名路径是目录或符号链接,接口返回错误并保留原路径。仅接受文件名为 1–128 位字母、数字、下划线或短横线加 .txt 后缀的 UTF-8 文本,单文件最大 16 KB,不能为空。不要修改微信提供的文件名或内容。

上传是管理操作,密钥由管理员保管;页面不将密钥存入 localStorage 或前端构建配置。支持通过 /admin/verification?secret=你的密钥 自动填入输入框,未提供或为空时手动填写;填入后会移除地址栏中的 secret,保留其他参数。URL 编码请使用 encodeURIComponent。该链接的初始请求仍可能被服务器或代理访问日志记录,应按敏感链接保管。不要使用 VITE_ 环境变量保存上传密钥。

架构与首次部署 ​

授权回调依然是静态页面;新增上传功能使用 server/verification-upload.mjs,需要额外的 Node.js 22.12+ 服务。服务无需 npm 依赖,仅监听 127.0.0.1:8787,由网站的 HTTPS Nginx 反向代理访问。

pnpm deploy / pnpm deploy:dist 只发布前端,不安装、启动或更新上传服务。 首次启用需完成以下步骤;后续改动服务端文件时需重新上传并重启该服务。前端回滚也不会自动回滚独立上传服务或 shared 中的文件。

方式一:宝塔面板 Node 项目(推荐) ​

本节对应宝塔“添加 Node 项目”中的「传统项目」界面。通过面板管理启动、停止、重启及环境变量,无需创建 systemd 服务。与下一节 systemd 方式二选一,不要让两个管理器同时启动同一服务,否则会争用 8787 端口。如果此前已通过 systemd 启动,应先停用旧服务并确认端口释放,再创建面板项目;切换期间上传接口会短暂不可用。

1. 准备 Node 和上传文件 ​

  1. 在宝塔“网站 → Node 项目”的 Node 版本管理入口安装或选择 Node.js 22.12.0 或符合项目要求的更高版本。不同面板版本菜单名称可能略有差异。
  2. 打开宝塔“文件”,创建 /opt/weixin-web-auth-upload,将本地 server/verification-upload.mjs 上传到该目录。
  3. 确认最终文件路径为 /opt/weixin-web-auth-upload/verification-upload.mjs,不是多套一层 server/ 的路径。服务没有第三方依赖,无需上传前端源码、dist、node_modules 或安装 pnpm。
  4. 通过文件管理检查 /www/wwwroot/webauth.wx.zhang520.cn/shared 已存在。该磁盘目录名与访问域名不同是正常的,必须使用服务器实际的持久化 shared 目录,不要指向 current 或某个版本目录。

2. 设置目录权限 ​

在宝塔文件管理中,对 shared 目录打开“权限”设置:

  • 所有者和用户组设为 www,目录权限为 755。
  • 仅调整 shared 目录本身,不勾选递归应用到子目录和文件,保留 .well-known 及现有文件的权限。
  • 上传服务文件通常设为 644,服务目录通常设为 755,其上级目录必须允许 www 遍历。

程序会在 shared 内创建临时文件,再重命名覆盖同名文件,因此 www 必须能写入 shared 目录。仅将已有 .txt 文件改成可写并不够。不要使用 777 或将运行用户改成 root 来替代正确的目录权限。

3. 填写「传统项目」表单 ​

进入“网站 → Node 项目 → 添加 Node 项目”,选择「传统项目」,按下表填写:

表单字段填写内容
项目名称weixin-txt-upload(若该项目已存在,直接进入项目设置修改,不要重复创建)
Node版本v22.12.0 或符合要求的已安装版本
启动文件/opt/weixin-web-auth-upload/verification-upload.mjs
运行目录/opt/weixin-web-auth-upload
参数留空;不要填写完整 node 命令或 --env-file

在「环境变量」文本框中填写,一行一个 key=value,不要加 export 或引号:

dotenv
UPLOAD_SHARED_DIR=/www/wwwroot/webauth.wx.zhang520.cn/shared
UPLOAD_ORIGINS=https://webauth.wx.ax3672.cn,https://webauth.wx.zhang520.cn
UPLOAD_PORT=8787
UPLOAD_TOKEN=替换为生成的64位随机密钥

密钥可在安装了 Node.js 的本机终端生成:

bash
node -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))"

将输出的完整字符串填入 UPLOAD_TOKEN,不要使用中文占位内容。密钥只用于本服务管理上传,不是微信 AppSecret,也不是 SSH 私钥。妥善保管,不要提交到 Git 或发到聊天中。

UPLOAD_ORIGINS 多个地址使用英文逗号分隔,每项包含协议,不带末尾 /、路径或查询参数;协议和端口精确匹配。兼容 UPLOAD_ORIGIN,两者同时配置时优先使用 UPLOAD_ORIGINS。这是允许打开管理页面的来源列表,不是后端监听地址。

本方式由面板注入环境变量,不需要 /etc/weixin-web-auth-upload.env,程序也不会自动读取该文件。若服务报环境变量错误,应检查面板中已保存的变量及运行日志。

展开“点击查看,更多配置”,若有对应字段:

配置项设置
项目端口8787,与 UPLOAD_PORT 一致
运行用户www
开机启动开启
域名绑定/外网映射不配置,继续使用现有静态网站的路径代理
防火墙端口放行无需对公网开放 8787

4. 创建并检查启动 ​

点击“确定”,在 Node 项目列表检查运行状态,再打开项目日志。默认端口下应看到:

text
Verification upload listening on 127.0.0.1:8787

该日志只说明服务已经监听,仍需完成接口代理和实际上传验证。开机启动不等于已经验证崩溃后自动重启,应以当前面板的进程管理能力为准。

报错或现象检查方式
UPLOAD_TOKEN must contain ...变量是否已保存;值是否为 32–256 位字母、数字、下划线或短横线,不带引号或中文
UPLOAD_ORIGINS / UPLOAD_ORIGIN must contain ...来源列表是否为空,是否包含路径、末尾斜杠、中文逗号或多余空项
ENOENT / 共享目录错误启动文件、运行目录和 shared 是否真实存在;shared 路径是否包含软链接
EADDRINUSE8787 是否被旧 systemd 服务或重复创建的 Node 项目占用
上传返回“保存失败,请检查共享目录和服务权限”优先核对运行用户和 shared 目录写权限;仍失败时检查日志、磁盘容量及文件系统状态,不能仅凭这条通用提示认定原因

5. 接入现有网站并测试 ​

完成下文“通用步骤:宝塔 Nginx 配置”和“通用步骤:发布页面并验收”。它们同时适用于面板与 systemd 两种方式。

不要将现有授权域名整站绑定到这个 Node 项目:后端仅提供上传 API,首页与回调页仍由已有静态网站提供。每个允许的域名都应有正确的 HTTPS 配置、上传 API 代理及 shared 校验文件读取规则。

6. 后续更新与重启 ​

修改服务代码后,在宝塔文件管理中先备份原 verification-upload.mjs,上传新文件覆盖,然后在 Node 项目列表中重启 weixin-txt-upload,核对日志并测试上传。修改面板环境变量后同样需要保存并重启。失败时恢复备份文件及原配置,再重启验证。

仅更新服务端无需构建前端;修改上传页面时需重新发布 dist。pnpm deploy 不会更新 /opt/weixin-web-auth-upload 中的文件,也不会自动重启面板 Node 项目。

方式二:systemd 常驻服务(可选) ​

本节仅供不使用宝塔 Node 项目管理服务的场景。已经完成方式一时,跳过本节,直接进入后面的通用 Nginx 配置。

1. 上传服务程序 ​

在宝塔安装 Node.js 22.12+,在 Linux 终端执行 node -v、command -v node 确认版本及实际可执行路径。下面 systemd 配置中的 /usr/bin/node 必须替换为该实际路径。

在 Linux 服务器执行(示例沿用现有站点目录):

bash
mkdir -p /opt/weixin-web-auth-upload
mkdir -p /www/wwwroot/webauth.wx.zhang520.cn/shared
# 宝塔默认 www 用户;若使用其他服务用户,所有位置保持一致。
chown www:www /www/wwwroot/webauth.wx.zhang520.cn/shared
chmod 755 /www/wwwroot/webauth.wx.zhang520.cn/shared

不需要递归修改 shared 既有文件和 .well-known 的所有权。上传服务通过在 shared 内创建临时文件并重命名替换目标文件,避免读到写入一半的内容;服务用户需要 shared 目录的写入权限。

在 Windows 项目根目录执行,修改服务器地址、端口及私钥路径:

powershell
scp -P 22 -i "$env:USERPROFILE/.ssh/weixin_web_auth_ed25519" ./server/verification-upload.mjs root@你的服务器IP:/opt/weixin-web-auth-upload/verification-upload.mjs

程序放在网站根目录之外,避免源码被静态服务公开访问。

2. 配置服务端密钥和环境 ​

在 Linux 终端生成随机密钥:

bash
node -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))"

用生成结果替换下方 UPLOAD_TOKEN。通过宝塔文件编辑器或终端创建 /etc/weixin-web-auth-upload.env,内容如下:

dotenv
UPLOAD_SHARED_DIR=/www/wwwroot/webauth.wx.zhang520.cn/shared
UPLOAD_ORIGINS=https://webauth.wx.ax3672.cn,https://webauth.wx.zhang520.cn
UPLOAD_PORT=8787
UPLOAD_TOKEN=替换为上一步生成的64位随机十六进制字符串

UPLOAD_ORIGINS 支持多个允许来源,以英文逗号分隔,逗号两侧空格会自动去除。每项必须为完整 HTTP(S) origin,包含协议和非标准端口(如有),不带路径、查询参数或末尾 /,不支持通配符或空项。协议、域名和端口精确匹配,列表外请求返回 403。兼容旧配置 UPLOAD_ORIGIN(也支持逗号分隔);两者同时设置时以 UPLOAD_ORIGINS 为准,显式设为空会报错,不会回退。每个使用的域名都需配置对应 HTTPS 站点和上传接口代理;此配置用于同源页面的来源校验,不开启跨域 CORS。共享目录必须已存在且路径不能包含软链接。密钥必须为 32–256 位字母、数字、下划线或短横线,示例占位符不能直接使用。

bash
chown root:root /etc/weixin-web-auth-upload.env
chmod 600 /etc/weixin-web-auth-upload.env
chmod 644 /opt/weixin-web-auth-upload/verification-upload.mjs

3. 启动常驻服务 ​

创建 /etc/systemd/system/weixin-web-auth-upload.service:

ini
[Unit]
Description=WeChat domain verification upload
After=network.target

[Service]
Type=simple
User=www
Group=www
EnvironmentFile=/etc/weixin-web-auth-upload.env
ExecStart=/usr/bin/node /opt/weixin-web-auth-upload/verification-upload.mjs
Restart=on-failure
RestartSec=3
UMask=0022
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/www/wwwroot/webauth.wx.zhang520.cn/shared
PrivateTmp=true

[Install]
WantedBy=multi-user.target

ExecStart 使用实际 Node 路径,确保 www 用户可执行它,且不位于被 ProtectHome=true 屏蔽的家目录中。然后执行:

bash
systemctl daemon-reload
systemctl enable --now weixin-web-auth-upload
systemctl status weixin-web-auth-upload --no-pager

排查日志:journalctl -u weixin-web-auth-upload -n 50 --no-pager。修改密钥或程序后运行 systemctl restart weixin-web-auth-upload。不要将 8787 端口开放到公网。

通用步骤:宝塔 Nginx 配置 ​

在该网站 HTTPS server 块中加入以下内容。已有相同 location 时编辑原配置;将以前仅匹配 MP_verify_*.txt 的规则替换为下面通用校验文件规则,使小程序提供的其他文件名也能读取。保留既有 SPA 回退和 .well-known 配置。

nginx
location = /api/verification-files {
    client_max_body_size 16k;
    client_body_timeout 30s;
    proxy_pass http://127.0.0.1:8787;
    proxy_set_header Host $host;
    proxy_set_header Authorization $http_authorization;
    proxy_set_header Origin $http_origin;
    proxy_read_timeout 35s;
    proxy_cache off;
}

# 放在可能匹配 .txt 的其他正则 location 之前。
location ~ "^/[A-Za-z0-9_-]{1,128}\.txt$" {
    root /www/wwwroot/webauth.wx.zhang520.cn/shared;
    types { }
    default_type text/plain;
    try_files $uri =404;
    add_header Cache-Control "no-store" always;
    add_header X-Content-Type-Options "nosniff" always;
}

在宝塔检查配置后重载 Nginx。页面需通过 HTTPS 使用,HTTP 应按现有规则跳转 HTTPS;保留证书签发需要的 HTTP .well-known 例外。不要将整个 shared 目录映射为可浏览目录,它包含证书验证等其他持久化文件。

按此规则,访问 https://webauth.wx.ax3672.cn/微信原文件名.txt 会直接读取 shared,上传后立即生效,不依赖重新发布。CDN 若缓存该路径,需同时禁用对应 .txt 缓存或清除旧缓存。

通用步骤:发布页面并验收 ​

执行 pnpm deploy 更新前端,然后访问 /admin/verification:

  1. 使用错误密钥上传,确认拒绝且服务器没有新文件。
  2. 使用正确密钥上传测试 .txt,打开返回链接,确认下载内容与本地文件完全相同。
  3. 修改测试文件内容后再次上传同名文件,确认公网链接返回新内容。
  4. 重新部署前端,再次读取该链接,确认文件仍存在。
  5. 上传微信原始校验文件并核对后,回到微信后台保存业务域名;测试文件用完后由管理员删除。

上传成功只代表已保存文件,不代表微信验证已通过。若链接返回首页 HTML,通常是 Nginx .txt 规则未生效;502 表示上传服务没有运行或代理端口错误;401 表示密钥错误;403 表示请求来源不在允许列表中;500 应检查目录写入权限和服务日志。

Windows 本地联调 ​

在项目根目录打开 PowerShell,创建 Git 忽略的本地目录并启动服务:

powershell
New-Item -ItemType Directory -Path .upload-local -Force | Out-Null
$env:UPLOAD_SHARED_DIR = (Resolve-Path .upload-local).Path
$env:UPLOAD_ORIGINS = 'http://localhost:5173'
$env:UPLOAD_TOKEN = node -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))"
# 复制输出的密钥到页面,仅用于当前本地测试。
$env:UPLOAD_TOKEN
pnpm upload:serve

另开终端运行 pnpm dev,访问 http://localhost:5173/admin/verification。Vite 已将上传 API 代理至本机 8787;如果 Vite 使用其他端口或主机名,请同步修改 UPLOAD_ORIGINS 并重启上传服务。本地上传写入 .upload-local,不会访问生产服务器;本地 Vite 不提供 shared 文件读取,成功后的公网校验链接需在配置 Nginx 的部署环境验收。

参考:Node.js 文件系统、Nginx 反向代理、Nginx 路由及文件读取。

宝塔「传统项目」可直接在环境变量输入框填写 UPLOAD_ORIGINS=https://webauth.wx.ax3672.cn,https://webauth.wx.zhang520.cn(整项一行,不加引号)。将更新后的 server/verification-upload.mjs 上传覆盖服务入口,保存配置并重启 Node 项目后生效;无需重新构建前端。

ESA 接入注意 ​

上传 API、管理页面(尤其含 secret 参数的地址)、根目录校验 .txt 和 ACME 路径必须配置绕过缓存。保留本页校验文件及后端 API 的 no-store,不要为了静态资源加速而全站删除。上线绕过规则时清理这些路径的历史缓存,随后验证同名文件覆盖可立即读取新内容。详见ESA 缓存配置。

微信服务号网页授权 · 接入与部署文档
皖ICP备2021000025号