Nginx可通过$secure_link变量值(""表签名校验失败、"0"表过期、"1"表通过)、自定义日志格式记录st/e/uri参数,并配合不同HTTP状态码(如402/405)实现防盗链失败原因的精准归因与日志追踪。

要记录 ngx_http_secure_link_module 防盗链失败的详细原因(比如签名错误、过期、参数缺失),Nginx 本身不直接输出“为什么拦截”,但可通过组合变量、自定义日志格式和状态码区分,实现精准归因。
1. 利用 $secure_link 变量区分三类失败
$secure_link 是核心判断变量,值只有三种可能:
- 空字符串(""):签名校验失败(密钥不匹配、URI 被篡改、MD5 参数格式错误)
-
"0":签名正确但已过期(
$arg_e或$arg_expires小于当前时间) - "1":验证通过(正常放行)
在 location 块中,不要只写 return 403,而是按值分别返回不同状态码,便于日志分类:
if ($secure_link = "") { return 402; } # 签名校验失败
if ($secure_link = "0") { return 405; } # 链接过期
2. 定义带上下文的自定义日志格式
在 http 块中添加日志格式,把关键诊断信息一并记入:
log_format secure_link_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'secure_link="$secure_link" '
'st="$arg_st" e="$arg_e" uri="$uri"';
其中:
-
secure_link="$secure_link"直接显示是 ""、"0" 还是 "1" -
st="$arg_st"和e="$arg_e"记录客户端传入的原始参数,方便比对是否为空、格式非法或时间戳异常 -
uri="$uri"确保路径未被重写干扰,用于核对secure_link_md5计算时使用的原始 URI
3. 在 location 中启用该日志并限制记录范围
避免全站日志膨胀,只对启用了 secure_link 的路径记录详细信息:
location /download/ {
secure_link $arg_st,$arg_e;
secure_link_md5 your_secret_key$uri$arg_e;
<pre class="brush:php;toolbar:false;"># 按结果分状态码
if ($secure_link = "") { return 402; }
if ($secure_link = "0") { return 405; }
# 成功时也记录(可选)
access_log /var/log/nginx/secure_link.log secure_link_log;
# 正常服务
alias /data/files/;}
这样,所有防盗链相关请求(含失败)都会进入 secure_link.log,且每条日志自带失败类型和原始参数快照。
4. 配合 error_log 查看模块级报错(可选)
如果出现 nginx: [emerg] unknown directive "secure_link" 或启动失败,说明模块未启用——这不是运行时防盗链失败,而是配置加载阶段错误。此时需检查:
-
nginx -V 2>&1 | findstr "secure_link"(Windows)或nginx -V 2>&1 | grep secure_link(Linux)是否有输出 - 确保使用的是含
--with-http_secure_link_module编译的 Nginx 二进制
这类问题不会出现在 access_log 中,必须查 error_log(默认在 logs/error.log)。











