Nginx secure_link模块可实现带签名的私密下载链接,通过校验MD5签名、过期时间及客户端IP(可选)防止未授权访问;需配置secure_link、secure_link_md5等指令,并在location中用if拦截失败请求,配合internal限制直接访问。

Nginx 的 secure_link 模块可用于实现带签名的私密下载链接,防止资源被未授权访问或盗链。它不依赖外部脚本,纯由 Nginx 在请求阶段校验签名、过期时间与客户端 IP(可选),适合轻量、高性能的临时授权分发场景。
启用 secure_link 并配置基本校验
确保 Nginx 已编译包含 ngx_http_secure_link_module(主流发行版默认开启)。在 http 块中定义 secure_link 相关指令:
-
secure_link $arg_md5,$arg_expires;:从 URL 查询参数提取签名(md5)和过期时间(expires),用逗号分隔 -
secure_link_md5 "$secure_link_expires$uri$remote_addr secret_key";:服务端按约定方式生成预期签名——将过期时间、请求 URI、客户端 IP(可选)与密钥拼接后取 MD5。注意:$remote_addr若需匹配,客户端必须真实 IP(非代理 IP),否则需配合real_ip模块修正 -
secure_link_expires $secure_link_expires;:提取并校验过期时间(Unix 时间戳),若已过期则变量值为 0,触发 403
设置 location 实现受控下载
在 server 或 location 块中使用 secure_link 的校验结果控制响应:
- 校验失败(签名错、过期、IP 不符)时,
$secure_link为空或 0,可用if拦截并返回错误:if ($secure_link = "") { return 403; } - 校验通过时,
$secure_link为非空字符串(如 "1"),可配合alias或root定向到真实文件路径,例如:alias /data/private/; - 推荐用
internal;防止直接访问原始路径,只允许通过带签名的链接跳转
生成合法签名链接(服务端示例)
签名逻辑必须和服务端配置严格一致。以 Python 为例生成一个 30 分钟有效、绑定客户端 IP 的链接:
- 假设文件路径为
/download/report.pdf,密钥为my_secret,当前时间为1717023600,过期设为+1800→expires = 1717025400 - 拼接字符串:
"1717025400/download/report.pdf192.168.1.100 my_secret"(注意空格和 IP 真实性) - 计算 MD5 得到 32 位小写哈希,如
a1b2c3d4e5f678901234567890abcdef - 最终链接:
https://example.com/download/report.pdf?md5=a1b2c3d4e5f678901234567890abcdef&expires=1717025400
注意事项与常见问题
签名密钥必须保密,不可硬编码在前端或日志中;时间同步很重要,Nginx 服务器与生成签名的服务时间差过大将导致频繁 403;避免在 URI 中暴露敏感路径,可配合重写隐藏真实文件结构;若使用 CDN 或反向代理,需确保 $remote_addr 取到真实客户端 IP(通过 X-Forwarded-For + set_real_ip_from);secure_link 不支持 HMAC 或自定义算法,如需更强安全性建议改用 secure_link_md5 的增强替代方案(如 OpenResty + Lua 加密)。










