secure_link 是 nginx 内置的时效性访问控制机制,通过时间戳、uri、客户端 ip 与密钥生成 md5 签名实现防伪造下载分发;需启用模块、配置 secure_link 与 secure_link_md5 指令,并确保前后端签名逻辑严格一致。

Secure_link 模块不是独立模块,而是 Nginx 官方内置的访问控制机制,需配合 secure_link、secure_link_md5 和 secure_link_secret(旧版)或更推荐的 secure_link_md5 + 变量签名(新版)使用。它不加密文件,而是通过时间戳+密钥+路径生成一次性签名,实现带时效、可验证、防伪造的受控下载分发。
一、确认 Nginx 已启用 secure_link 模块
该模块默认编译进大多数主流发行版的 Nginx(如 Ubuntu 的 nginx-full、CentOS 的 nginx-mod-http-secure-link)。验证方式:
- 运行
nginx -V 2>&1 | grep -o with-http_secure_link_module,有输出即支持 - 若无,需重新编译 Nginx 并添加
--with-http_secure_link_module
二、基础防盗链配置(基于 secure_link_md5)
适用于静态资源(如 /dl/xxx.zip),要求 URL 形如 /dl/file.zip?md5=xxx&expires=1717027200:
- 在
location /dl/块中添加:
location /dl/ {
secure_link $arg_md5,$arg_expires;
secure_link_md5 "$secure_link_expires$uri$remote_addr your_secret_key";
<pre class="brush:php;toolbar:false;">if ($secure_link = "") {
return 403;
}
if ($secure_link = "0") {
return 403;
}
# 签名有效且未过期,正常提供文件
alias /var/www/downloads/;}
-
$arg_md5和$arg_expires分别读取 URL 中的md5和expires参数 -
secure_link_md5表达式必须与后端生成签名时完全一致:含过期时间(秒级时间戳)、URI 路径、客户端 IP(增强绑定)、固定密钥 -
$secure_link变量为""表示参数缺失,"0"表示签名错误或已过期
三、升级为动态签名(推荐:支持用户粒度+IP 绑定+灵活策略)
避免硬编码密钥和简单拼接,改用 map + secure_link_md5 实现多密钥或条件签名:
- 定义密钥映射(按用户ID或域名区分):
map $arg_uid $secret_key {
default "fallback_key_2024";
~^[0-9]{6}$ "user_${arg_uid}_key";
"vip@site.com" "vip_special_key";
}
- 在 location 中引用:
location /dl/ {
secure_link $arg_sig,$arg_e;
secure_link_md5 "$arg_e$uri$arg_uid$remote_addr$secret_key";
<pre class="brush:php;toolbar:false;">if ($secure_link = "") { return 400; }
if ($secure_link = "0") { return 403; }
# 额外校验:确保 expires 未被篡改(防止重放)
if ($arg_e !~ ^[0-9]{10}$) { return 400; }
if ($arg_e <p>}
</p>- 此时下载链接形如:
/dl/game.zip?uid=123456&sig=abc123&e=1717027200 - 服务端生成 sig 时,用相同公式:MD5( e + uri + uid + remote_addr + secret_key ),前8位即可
- 支持按用户 ID 动态切密钥,IP 绑定防 token 泄露后被他人复用
四、后端生成安全链接(Python 示例)
不要前端计算签名,必须由可信后端生成并下发:
import time
import hashlib
<p>def gen_secure_url(filename, uid, ip, secret):
expires = int(time.time()) + 3600 # 1小时有效期
raw = f"{expires}/dl/{filename}{uid}{ip}{secret}"
sig = hashlib.md5(raw.encode()).hexdigest()[:8]
return f"/dl/{filename}?uid={uid}&sig={sig}&e={expires}"</p>- 注意 URI 路径需与 Nginx 中
$uri完全一致(如带前缀/dl/) - 务必校验
uid合法性、限制单用户并发链接数、记录签发日志用于审计 - 敏感文件建议搭配
X-Accel-Redirect内部重定向,不暴露真实路径
不复杂但容易忽略:签名逻辑前后端必须严格一致;时间戳用 Unix 秒;Nginx 时间需与后端服务器同步(启用 NTP);生产环境禁用 secure_link_secret(已废弃且不支持变量)。











