Nginx+secure_link实现防盗链鉴权

上次用Nginx做了个防盗链,后面经群里大佬指点发现Nginx防盗链除了我的那种做法以外还有鉴权的玩法,就蛮做一下试试。
一、环境

CentOS7.9
Nginx 1.22.1

二、步骤

1、编译安装Nginx
这里用到了一个模块叫做secure_link_module

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
wget https://nginx.org/download/nginx-1.22.1.tar.gz
tar -zxvf nginx-1.22.1.tar.gz
cd nginx-1.22.1

./configure --prefix=/usr/local/nginx \
--with-http_realip_module \
--with-http_secure_link_module \
--with-http_sub_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-http_v2_module \
--with-stream \
--with-openssl=/usr/local/openssl/ \
--with-pcre=/usr/local/pcre-8.32/ \
--with-zlib=/usr/local/zlib-1.2.13/ \
--add-module=/usr/local/ngx_http_geoip2_module-3.3

2、配置nginx防盗链

1
2
mkdir -p /usr/local/nginx/conf/v_host/
vim /usr/local/nginx/conf/nginx.conf

在配置文件的最后一样,也就是}的上面加上这句

1
include /usr/local/nginx/conf/v_host/website.conf;

配置虚拟主机的文件(防盗链鉴权)

1
vim /usr/local/nginx/conf/v_host/website.conf
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
server {
listen 80;
charset utf-8;
server_name website.abc.com;
client_max_body_size 300m;
access_log /usr/local/nginx/logs/website_access.log;
error_log /usr/local/nginx/logs/website_error.log debug;
gzip on;
gzip_comp_level 9;
gzip_types text/css text/plan text/xml application/javascript application/x-javascript application/html application/xml image/png image/jpg image/jpeg image/gif image/webp image/svg+xml;

location /{
root /www/website/;
index index.html index.htm;

#设置一个密钥
set $sec 123456;

#设置鉴权参数,arg_sign就是sign,arg_t就是t
#完整的是http://website.abc.com/nihao/hello/1.jpg?sign=&t=
secure_link $arg_sign,$arg_t;

#计算md5的值是多少,md5的值是由密钥、url、时间戳组成算出来
#例如:123456/nihao/hello/1.jpg/1577861373这样计算出来的
secure_link_md5 "$sec$uri$arg_t";

#进行判断,如果用户提交的md5值和时间戳与计算出来的不一致,则为空,返回403代码
if ($secure_link = "") {
return 403;
}

#进行判断,如果用户提交的md5值和时间戳是过期的,则为0,返回410代码
if ($secure_link = "0") {
return 410;
}
}
}

3、重启nginx

1
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

4、写个php方便我们测试

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

<?php

$host = 'http://website.abc.com';
$uri = '/nihao/hello/1.jpg';
$sec = '123456'; // 密钥,和Nginx配置保持一致,我们nginx这里配置的sec,所以这里也要跟着写sec
$t = 1800; // 文件有效时间,单位秒,可自定义
$time = time() + $t;

// Step 1: 对连接后的字符串进行 MD5 哈希计算
$md5_value = md5($sec . $uri . $time,true);
echo "MD5 value: $md5_value \n";

// Step 2: 将 MD5 值编码为 Base64 格式
$base64_value = base64_encode($md5_value);
echo "Base64 value: $base64_value\n";

// Step 3: 对 Base64 值进行替换操作,删除等号(=)并替换字符
$token = str_replace('=', '', strtr($base64_value, '+/', '-_'));
echo "Token: $token\n";

// Step 4: 在 URL 中添加令牌参数和时间戳参数
$final_url = "$host$uri?sign=$token&t=$time";
echo "Final URL: $final_url\n";
?>

5、测试下效果

正常访问http://website.abc.com/nihao/hello/1.jpg,会报403,因为没鉴权

未鉴权

带鉴权参数访问则正常
先访问刚才创建的php,来获得完整的带有鉴权参数的链接

自动计算

鉴权

鉴权过期后再访问则显示410

过期鉴权

三、总结

大致就是用secure_link的模块来做鉴权,然后把系统计算出来的值跟用户提交的值作对比,比不上就是鉴权失败。

戴戴的Linux

文章目录
  1. 1. 上次用Nginx做了个防盗链,后面经群里大佬指点发现Nginx防盗链除了我的那种做法以外还有鉴权的玩法,就蛮做一下试试。
  2. 2. 一、环境
  3. 3. 二、步骤
  4. 4. 三、总结


本站总访问量 本文总阅读量