nginx secure_link模块可生成和验证带签名、有时效性的静态资源链接,防止盗链和滥用;它纯内置实现,需启用--with-http_secure_link_module,通过secure_link与secure_link_md5指令校验st签名和e过期时间,失败时$secure_link为空,成功为"1"。

Nginx 的 secure_link 模块可用于生成和验证带签名、有时效性的静态资源链接,防止资源被未授权盗链或长期滥用。它不依赖外部服务,纯 Nginx 内置实现,轻量且高效。
启用 secure_link 并配置基础校验逻辑
确保编译 Nginx 时已启用 --with-http_secure_link_module(主流发行版包通常默认包含)。在 location 块中使用 secure_link 和 secure_link_md5 指令:
-
secure_link $arg_st,$arg_e;:从 URL 查询参数中提取签名(st)和过期时间(e),用逗号分隔 -
secure_link_md5 "secret_key$uri$arg_e";:服务端按约定方式拼接原始字符串并计算 MD5,与$arg_st比对 - 若签名无效或已过期(
$arg_e ),Nginx 将设 <code>$secure_link = "";校验通过则为"1"
生成合法的带时间戳链接(服务端示例)
链接格式形如:https://example.com/file.zip?st=xxx&e=1717027200。生成步骤需严格一致:
- 确定资源路径(如
/file.zip),注意必须与 Nginx 配置中$uri完全一致(不含查询参数,也不含重写后的路径) - 设定 Unix 时间戳过期时间(如 2 小时后:
time() + 7200) - 拼接字符串:
secret_key + /file.zip + "1717027200"(无空格、无编码),再取其 MD5 前 16 字节的 Base64 URL 安全编码(去掉=、替换+//) - 将结果作为
st参数值,时间戳作为e参数值
例如 Python 快速生成:
import hashlib, base64, time<br>uri = "/file.zip"<br>expires = int(time.time()) + 7200<br>key = "my_secret"<br>raw = f"{key}{uri}{expires}"<br>md5 = hashlib.md5(raw.encode()).digest()[:16]<br>st = base64.urlsafe_b64encode(md5).decode().rstrip('=')<br>print(f"https://example.com{uri}?st={st}&e={expires}")
在 Nginx 中拦截非法请求并返回友好响应
利用 $secure_link 变量做条件判断,拒绝非法访问:
- 添加
if ($secure_link = "") { return 403; }直接拦截失败请求 - 可选:用
error_page 403 /403.html;返回自定义提示页 - 注意:避免在
if中使用rewrite或复杂逻辑;secure_link仅适用于 GET/HEAD 请求,不适用于代理场景 - 若需支持子目录或变量 URI,确保
$uri在secure_link_md5中准确反映最终文件路径(必要时用$request_uri或重写后变量)
调试与常见陷阱
校验失败往往源于细微不一致,建议逐项核对:
- 密钥(
secret_key)前后端必须完全相同,包括大小写、空格、不可见字符 -
$uri是解码后的路径,如请求/file%2Ftest.zip,实际$uri为/file/test.zip,拼接时必须用此形式 - 时间戳单位是秒,且必须为整数;服务端与客户端系统时间偏差超过过期窗口会导致提前失效
- Base64 编码必须截取 MD5 前 16 字节(128 位),并使用 URL 安全变体(
_替+,-替/),末尾=应去除 - 开启
error_log debug;可查看 secure_link 校验过程日志(需重新编译时加--with-debug)











