nginx 的 secure_link 模块通过验证 url 中的签名参数来实现下载防盗链。具体做法是在 nginx 配置中定义密钥,并使用 md5 或 sha1 算法生成包含时间戳和资源的签名串,将其附加到资源链接后。当请求到达时,nginx 会重新计算签名并与请求中的参数比对,若一致则允许访问,否则返回 403 错误。

secure_link 如何验证请求合法性
该模块通过比较客户端传入的签名与服务器端基于相同密钥和参数计算的签名来验证请求。如果签名匹配且未过期,则视为合法;否则拒绝访问。核心在于正确构造签名字符串并配置相应的校验规则。

location /download/ {
# 定义密钥
set $secret_key "my_secret_key";
# 提取 URL 中的签名和时间戳
secure_link "$arg_md5,$arg_expires";
# 验证逻辑:
# 1. 检查签名是否存在
# 2. 检查签名是否有效(非空)
# 3. 检查时间戳是否过期
if ($secure_link = "") {
return 403 "Forbidden";
}
if ($secure_link = "0") {
return 403 "Signature expired or invalid";
}
# 如果验证通过,继续处理请求
try_files $uri =404;
}上述配置中,$arg_md5 和 $arg_expires 分别对应 URL 查询参数中的 ?md5=... 和 ?expires=...。secure_link 指令将这两个值赋给内部变量 $secure_link。如果签名无效或已过期,$secure_link 会被设置为空字符串或 0,从而触发 if 语句返回 403 错误。
如何生成有效的签名 URL
生成签名需要使用与 Nginx 配置中相同的密钥、资源路径和时间戳,按照特定格式拼接后进行哈希运算。通常使用 md5sum 或类似工具在命令行或脚本中生成签名,然后将其拼接到资源 URL 中。

# 假设资源路径为 /download/file.zip
# 密钥为 my_secret_key
# 过期时间为当前时间 + 3600 秒
EXPIRES=$(date -d '+1 hour' +%s)
RESOURCE="/download/file.zip"
SECRET="my_secret_key"
# 生成签名:MD5(Expires + Resource + Secret)
SIGNATURE=$(echo -n "${EXPIRES}${RESOURCE}${SECRET}" | md5sum | awk '{print $1}')
# 构建最终 URL
echo "http://example.com/download/file.zip?expires=${EXPIRES}&md5=${SIGNATURE}"生成的 URL 示例:http://example.com/download/file.zip?expires=1717027200&md5=a1b2c3d4e5f6...。此 URL 在指定时间内有效,超过时间后 Nginx 会拒绝访问。注意,echo -n 确保不添加换行符,保证签名一致性。
如何处理签名冲突或重复请求
由于 secure_link 仅依赖签名和时间戳,同一签名在有效期内可被多次使用,无法防止重复下载。若需限制单次访问,需结合其他机制如 IP 白名单或会话管理。此外,若密钥泄露,所有基于该密钥的签名都将失效,因此密钥应妥善保管。


















