Nginx的secure_link模块可通过URL签名与时间戳实现视频防盗链和时效控制;需启用模块,配置secure_link及secure_link_md5校验规则,服务端生成含st/e参数的URL,确保密钥保密、拼接一致、日志脱敏。

用 Nginx 的 secure_link 模块可以实现简单但有效的视频 URL 防盗链与时效控制,无需额外服务或复杂鉴权系统,适合中小型点播场景。
原理与前提条件
secure_link 是 Nginx 官方模块(需编译启用,主流发行版的包通常已包含),它通过 URL 中携带的加密签名 + 时间戳,由 Nginx 在服务端校验合法性。核心逻辑是:客户端请求带签名和过期时间,Nginx 用预设密钥重新计算签名并比对,同时检查时间戳是否未过期。
注意:该模块不加密视频内容本身,只保护访问链接;密钥必须严格保密,不可泄露到前端或日志中。
配置 secure_link 校验规则
在 server 或 location 块中添加如下配置:
location /video/ {
# 从 URL 提取 $arg_st(签名)、$arg_e(过期时间戳)
secure_link $arg_st,$arg_e;
secure_link_md5 "your_secret_key$uri$arg_e";
<pre class="brush:php;toolbar:false;"># 校验失败:签名错、时间过期、参数缺失 → 返回 403
if ($secure_link = "") {
return 403;
}
# 时间已过期 → 返回 410
if ($secure_link = "0") {
return 410;
}
# 校验通过,正常提供文件(假设视频存于 /data/videos/)
alias /data/videos/;}
说明:
-
$arg_st和$arg_e分别对应 URL 中的st和e参数(可自定义名,但需前后一致) -
secure_link_md5后的字符串是服务端用于生成签名的“盐”,必须包含 URI 路径和时间戳,确保链接绑定资源与有效期 -
$secure_link变量值为""表示参数缺失或签名无效;为"0"表示签名正确但时间已过期
生成合法播放链接(服务端示例)
以 Python 为例,生成带签名和过期时间的 URL:
import hashlib
import time
<p>uri = "/video/movie.mp4"
secret = "your_secret_key"
expires = int(time.time()) + 3600 # 1 小时后过期</p><h1>拼接并计算 MD5(注意:Nginx 内部用的是小写十六进制,且不加空格)</h1><p>to_hash = f"{secret}{uri}{expires}".encode()
st = hashlib.md5(to_hash).hexdigest()</p><p>url = f"<a href="https://www.php.cn/link/5d62b2a1b238ccd332ca30b6714023d1">https://www.php.cn/link/5d62b2a1b238ccd332ca30b6714023d1</a>}"</p>
生成的 URL 类似:https://example.com/video/movie.mp4?st=8a7f...&e=1731234567
关键点:
- 签名计算必须与 Nginx 中
secure_link_md5的拼接顺序、内容完全一致 - 时间戳使用 Unix 秒级整数,Nginx 会直接比较数值大小
- 建议在服务端生成链接并下发给用户(如通过 API 或模板渲染),避免前端参与签名
增强可用性与安全性建议
基础配置可用,但生产环境建议补充以下措施:
-
限制 IP 或 Referer:在
secure_link校验通过后,叠加valid_referers或geo+map控制来源 -
隐藏真实路径:用
alias或proxy_pass指向内部存储,避免暴露文件系统结构 -
日志脱敏:在 access_log 中过滤掉
st和e参数,防止密钥推断或重放分析 -
配合防盗链头:添加
add_header X-Content-Type-Options nosniff;和add_header Content-Disposition "inline";防止误下载或 MIME 嗅探
不复杂但容易忽略。











