Nginx secure_link模块可生成带签名和时效的下载链接以防止盗链;通过secure_link与secure_link_md5指令校验URL参数中的md5和expires,配合if拦截非法请求,全程内置、轻量高效。

Nginx 的 secure_link 模块可用于生成带签名、有时效性的下载链接,防止资源被未授权盗链或长期滥用。它不依赖外部服务,纯靠 Nginx 内置指令完成校验,轻量且高效。
启用 secure_link 模块并配置基础校验
确保编译 Nginx 时已启用 --with-http_secure_link_module(主流发行版预装包通常默认包含)。在 location 块中使用 secure_link 和 secure_link_md5 指令:
-
secure_link $arg_md5,$arg_expires;:从 URL 参数中提取签名(md5)和过期时间(expires),赋值给内置变量 -
secure_link_md5 "$secure_link_expires$uri$remote_addr$secret_key";:服务端按约定规则生成期望的 MD5 签名;其中$secret_key是自定义密钥,必须与生成链接时一致 - 若校验失败(签名不匹配或时间已过),
$secure_link变量值为空或 0,可配合if返回 403
生成合法的时效加密链接
链接格式为:https://example.com/file.zip?md5=xxx&expires=1717027200。生成逻辑需严格对齐 Nginx 校验规则:
- 取 Unix 时间戳(秒级)作为
expires,例如 2 小时后:$(date -d '+2 hours' +%s) - 拼接字符串:
"${expires}${uri}${client_ip}${secret_key}"(注意顺序和字段含义,$uri是不含参数的路径,如/file.zip;$client_ip应与 Nginx 中$remote_addr一致,若前端有代理,需用$http_x_forwarded_for并确保可信) - 计算 MD5(小写 32 位):如
echo -n "1717027200/file.zip192.168.1.100my_secret" | md5sum | cut -d' ' -f1
结合时间校验与访问控制
仅校验签名不够,还需拦截过期请求:
- 在
secure_link指令后添加if ($secure_link = "") { return 403; }拦截签名错误或过期链接 - 也可用
if ($secure_link_expires 显式比对时间(需开启 <code>secure_link解析) - 建议将资源放在非公开目录,通过
alias或root配合内部重定向(internal;)进一步限制直接访问
注意事项与常见问题
实际部署中容易忽略的关键点:
- 密钥
$secret_key必须保密且前后端一致;轮换密钥时需同步更新所有链接生成逻辑 - 时间必须用服务器本地时区的 Unix 时间戳,避免客户端和服务端时间偏差导致误判;建议 NTP 同步
-
$remote_addr在反向代理场景下是代理 IP,应改用可信的客户端 IP(如$http_x_real_ip),并在 proxy_pass 中设置proxy_set_header X-Real-IP $remote_addr; - 该模块不支持 HMAC 或 SHA256,仅限 MD5;如需更高安全性,可考虑用 Lua(OpenResty)或外部鉴权服务替代











