Nginx http_secure_link模块使用
小轲

什么是http_secure_link模块?

secure_link机制简单来说就是来保护你的http资源被受控访问的,类似于防盗链、http授权访问的Token。假如你有一些私有化的、需验证身份才能访问的资源,就可以使用这个机制。

下面是一个简单的流程,分为两步

  1. 请求授权:携带目标uri,在后端鉴权通过后计算签名。
    1. 签名的规则通常是uri+secret+expire来生成
  2. 携签名访问资源: 携带url?sign=xxxx&expire=1731313131来访问
    1. 参数说明:
      1. sign携带API返回的签名
      2. expire 过期时间戳

下面是简单的流程图

image

核心代码

代码涉及两个部分,一个是nginx网关部分。另一部分则为核心的API。

API

代码使用Go语言,出入参非常简单。

注意:sign在全链路下是无状态的,也就是泄漏后依然会有风险,推荐expire时间设置为分钟级,过期后拒绝请求可再签来实现安全性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package service

import (
"crypto/md5"
"encoding/base64"
"fmt"
"strings"
)

// GenerateSignature 生成URI访问签名
//
// 参数:
// uri - 请求的URI路径
// expire - 签名过期时间戳(秒)
// secret - 签名密钥
//
// 返回值:
// string - 生成的签名字符串
//
// 实现原理:
// 1. 按照Nginx兼容格式拼接expire、uri和secret
// 2. 对拼接字符串进行MD5哈希计算
// 3. 哈希结果进行Base64 URL编码并去除末尾等号
func GenerateSignature(uri string, expire int64, secret string) string {
// 严格匹配 Nginx 的字符串格式:${expire}${
//
//uri} ${secret}
raw := fmt.Sprintf("%d%s %s", expire, uri, secret)
hash := md5.Sum([]byte(raw))
// Base64 编码 + 替换特殊字符(与 Nginx 兼容)
return strings.TrimRight(
base64.URLEncoding.EncodeToString(hash[:]), "=",
)
}

Nginx

nginx无需任何插件即可实现该功能,而且http_secure_link是nginx的worker内特性。还是无状态check,所以不存在太多的性能问题,不会拖慢nginx的响应速度。

  1. secret 必须与 GenerateSignature 函数中的secret参数完全一致,否则无法过签名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
worker_processes 1;

events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;

server {
listen 80;
server_name localhost;

location /protected/ {
secure_link $arg_st,$arg_exp;
# secret 记得更换
secure_link_md5 "$arg_exp$uri secret";

if ($secure_link = "") {
return 403; # Bad hash
}
if ($secure_link = "0") {
return 410; # Expired
}

# 明确指定文件物理路径别名
alias /usr/share/nginx/static/;
}

location / {
root /usr/share/nginx/html;
index index.html;
}
}
}

总结

该场景下可以实现部分api、static、html的保护访问,可以做到http访问保护。但是一定要注意时间问题,尽量保证泄露的风险最小。

本例如有demo、技术支持需求,欢迎在下面评论~

参考文章

  1. https://nginx.org/en/docs/http/ngx_http_secure_link_module.html
  2. https://nginx.ac.cn/en/docs/http/ngx_http_secure_link_module.html
  3. https://www.cnblogs.com/panwenbin-logs/p/8728327.html
 评论
评论插件加载失败
正在加载评论插件