Nginx 的 secure_link_md5 指令通过 URL 中 st(MD5签名)和 e(过期时间戳)实现无状态鉴权,校验路径+密钥+时间戳三元组,需前后端路径、密钥严格一致,并建议分钟级过期、限流及文件名脱敏。

使用 Nginx 的 secure_link_md5 指令可实现轻量、高效、无状态的下载链接鉴权,适用于静态资源(如 PDF、ZIP、安装包)分发场景。它不依赖后端数据库或会话,靠 URL 中嵌入的签名与时间戳完成校验,兼顾时效性与防篡改能力。
核心原理:签名 + 时间戳 + 密钥三元校验
客户端请求的 URL 形如:https://example.com/file.zip?st=xxx&e=1717027200
其中:
-
st 是对
路径 + 过期时间 + 密钥做 MD5(实际为 base64url 编码的前 16 字节) - e 是 Unix 时间戳,表示过期时刻(单位秒)
- Nginx 在
secure_link指令中解析参数,用相同密钥重新计算 st,并比对是否一致、e 是否未过期
配置要点:Nginx 端必须严格对齐
在 server 或 location 块中启用鉴权:
location /files/ {
secure_link $arg_st,$arg_e;
secure_link_md5 "your_secret_key$uri$arg_e";
<pre class="brush:php;toolbar:false;">if ($secure_link = "") {
return 403;
}
if ($secure_link = "0") {
return 410; # 已过期
}
alias /data/static/;}
- 密钥
"your_secret_key"必须与生成链接时完全一致,建议存于环境变量或加密配置文件中 -
$uri包含前导斜杠(如/files/report.pdf),需确保前后端路径拼接逻辑统一 - 避免在
secure_link_md5中引入动态变量(如 $host),否则校验必然失败
生成安全链接:服务端代码示例(Python)
生成带签名和过期时间的下载地址:
import time
import hashlib
import base64
<p>def gen_secure_url(path: str, secret: str, expires_in: int = 3600) -> str:
expires_at = int(time.time()) + expires_in</p><h1>注意:Nginx 内部使用原始字节 MD5 前 16 字节,再 base64url 编码(去=、+、/)</h1><pre class="brush:php;toolbar:false;">raw = f"{secret}{path}{expires_at}".encode()
md5_bytes = hashlib.md5(raw).digest()[:16]
st = base64.urlsafe_b64encode(md5_bytes).decode().rstrip("=")
return f"https://example.com{path}?st={st}&e={expires_at}"</code>- 务必使用
urlsafe_b64encode 并去除末尾 <code>=,否则 Nginx 解析失败 - 路径
path必须与 Nginx 中$uri完全一致(含斜杠、编码格式) - 过期时间建议控制在分钟级(如 5–30 分钟),兼顾安全性与用户体验
生产增强建议:防重放与最小权限
仅靠 secure_link_md5 不足以应对所有攻击,需叠加基础防护:
- 限制 HTTP 方法:只允许 GET,拒绝 HEAD/POST 请求
- 添加 Referer 白名单(可选):
valid_referers none blocked example.com; - 配合限流:对
/files/路径启用limit_req,防暴力猜测 - 敏感文件不直接暴露真实路径名,用 UUID 替代原始文件名(如
/files/a1b2c3d4.zip),降低信息泄露风险

















