Nginx可通过secure_link模块实现静态资源限时访问保护:配置secure_link指令校验base64url编码的MD5签名与过期时间戳,匹配则放行,否则返回403或410;需配合限制请求方法、禁用缓存及外部存储密钥等安全增强措施。

要实现静态资源的限时访问保护,核心是让 URL 包含可验证的时间戳和签名,Nginx 在收到请求时实时校验时间有效性与签名正确性,通过则放行,否则返回 403。这无需后端参与,纯 Nginx + ngx_http_rewrite_module 即可完成。
URL 签名结构设计
约定签名 URL 格式为:/static/file.jpg?expires=1745164800&sign=abc123,其中:
- expires 是 Unix 时间戳(秒级),表示该链接过期时间
-
sign 是服务端按规则生成的哈希值,例如
md5("/static/file.jpg?expires=1745164800" + SECRET_KEY) - 签名不包含
sign=xxx参数本身,避免循环依赖 - 路径和参数顺序需严格一致(建议固定为
path?expires=xxx)
Nginx 配置关键段:校验时间与签名
在 server 或 location 块中启用 rewrite 模块逻辑,用 map 提前提取变量,再用 if 判断:
map $args $expires_time {
~*expires=(\d+) $1;
default "";
}
<p>map $args $sign_in_url {
~*sign=([^&]+) $1;
default "";
}</p><p>location ^~ /static/ {</p><h1>检查 expires 是否存在且为数字</h1><pre class="brush:php;toolbar:false;">if ($expires_time = "") {
return 403;
}
# 检查是否已过期
if ($expires_time <p>}</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill6848" title="Nginx Hosting"><img
src="https://img.php.cn/upload/skill/000/000/081/179116929868126.jpg" alt="Nginx Hosting" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill6848" title="Nginx Hosting" class="overflowclass">Nginx Hosting</a>
<p class="overflowclass">通过服务器本地nginx实例实现零认证静态游戏托管。作为所有浏览器游戏的主要部署方式,无需登录、无需令牌、无需用户操作。</p>
</div>
<a rel="nofollow" href="/xiazai/skill6848" title="Nginx Hosting" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>更推荐:用 secure_link 替代手工 rewrite 签名
虽然 rewrite 可实现,但签名计算在 Nginx 中受限(无原生 HMAC/MD5 函数),易出错且难调试。生产环境强烈建议改用 ngx_http_secure_link_module(默认编译进大多数发行版):
- 客户端 URL 示例:
/static/file.jpg?st=oQwF9XzLbYVJmRqKtUvWxYzA&e=1745164800 -
st是 base64url 编码的 MD5(Secret + URI + Expiration),e是过期时间戳 - Nginx 配置只需几行:
location ^~ /static/ {
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 403;
}
if ($secure_link = "0") {
return 410; # 链接过期
}}
签名生成示例(Python):
import hashlib, base64, time
uri = "/static/file.jpg"
secret = "YOUR_SECRET_KEY"
expires = int(time.time()) + 3600 # 1小时后过期
to_hash = f"{secret}{uri}{expires}"
st = base64.urlsafe_b64encode(hashlib.md5(to_hash.encode()).digest()).decode().rstrip("=")
url = f"{uri}?st={st}&e={expires}"
安全增强建议
仅靠签名还不够,还需补充防护细节:
- 限制签名 URL 只能用于 GET 请求,拒绝 POST/HEAD 等方法:
if ($request_method != GET) { return 405; } - 禁止缓存签名链接,避免 CDN 或浏览器长期持有有效链接:
add_header Cache-Control "no-store, no-cache, must-revalidate"; - 将 SECRET_KEY 存于 Nginx 外部文件(如
/etc/nginx/secrets/key),用include引入,避免硬编码在配置中 - 对敏感资源目录(如
/private/)单独设置 location,避免误放行










