nginx secure_link下载防盗链

2,118 阅读2分钟

Nginx ngx_http_secure_link_module模块能够检查请求链接的权限以及是否过期,多用于下载服务器防盗链。

原理

1)加密串与过期时间作为url中的参数

2)nginx服务器接收到了过期时间,也使用过期时间、配置里密钥、文件uri生成加密串

3)计算的加密串与url传递的加密串进行对比

开启ngx_http_secure_link_module

./configure --with-http_secure_link_module #编译nginx时加入

secure_link

语法: secure_link expression; 
默认值: 无 
配置段: http, server, location

说明 expression由校验值和过期时间组成,其中校验值将会与secure_link_md5中的指定参数的MD5哈希值进行对比,如果两个值不一致,则secure_link变量的值是空,如果两个值一致,则进行过期检查,如果过期了,则$secure_link变量值是0,如果没过期,则为1。

如果链接是有时效性的,那么过期时间用时间戳进行设置,在MD5哈希值后面声明,用逗号隔开。如果没有设置过期时间,该链接永久有效。

secure_link_md5

语法 
语法: secure_link_md5 expression; 
默认值: 无 
配置段: http, server, location

说明 expression指定计算md5哈希值的参数,该md5值将会和url中传递的md5值进行对比校验。expression一般包含uri以及加密密钥secret,如果该链接具有时效,则expression需包含$secure_link_expires,expression还可以加入客户端信息,如访问IP,浏览器版本信息等

实例

nginx配置

location /s/ {
    secure_link $arg_md5,$arg_expires; #这里配置了2个参数一个是arg_md5,一个是arg_expires
    secure_link_md5 "123456$uri$arg_expires"; #123456为自定义的加密串(这里的md5加密顺序要和程序生成的加密顺序保持一致)   

    if ($secure_link = "") {
        return 403; #资源不存在或哈希比对失败
    }

    if ($secure_link = "0") {
        return 410; #时间戳过期 
    }
}

注:

1、secure_link模块将取到参数名为md5和参数名为expires两个值。

2、secure_link_md5将使用secure_link_expires的值和uri的值与后面的加密串shareSecret进行加密。

3、若$secure_link为非空或者不为0,则可以进行下载。

在php中生成访问url

####密钥
$secret = '123456';

####下载文件,切记路径带上/
$path = "/images/share.jpg";

####下载到期时间,time是当前时间,$validtime表示有效期,也就是说从现在到300秒之内文件不过期
$validtime = 300;
$expire = time() + $validtime;

####用文件路径、密钥、过期时间生成加密串(注意这里的md5加密顺序要和nginx配置文件中的顺序保持一致)
$md5 = base64_encode(md5($secret . $path . $expire, true));
$md5 = strtr($md5, '+/', '-_');
$md5 = str_replace('=', '', $md5);

####加密后的下载地址
$uri = $path . '?md5=' . $md5 . '&expires=' . $expire;

####安全下载链接可以直接echo输出
$uri = "http://api.xxx.cn" . $uri;
echo $uri;

复制该链接,浏览器可以进行下载。

链接修改md5或者expires其中任何一个,都会出现禁止访问。


nginx 通过referer实现图片防盗链

location ~* \.(gif|jpg|png|webp)$ {
    valid_referers none blocked domain.com *.domain.com server_names ~\.google\. ~\.baidu\.;
    if ($invalid_referer) {
        return 403;
        #rewrite ^/ http://www.domain.com/403.jpg;
    }
}

以上所有来至domain.com的域名以及baidu和google的站点都可以访问到当前站点的图片,如果来源域名不在这个列表中,那么$invalid_referer等于1,在if语句中返回一个403给用户,这样用户便会看到一个403的页面,如果使用rewrite,那么盗链的图片都会显示403.jpg。none规则实现了允许空referer访问,即当直接在浏览器打开图片时,图片仍能正常显示

指令

语法: valid_referers none | blocked | server_names | string …;

配置段: server, location

指定合法的来源referer, 他决定了内置变量$invalid_referer的值,如果referer头部包含在这个合法网址里面,这个变量被设置为0,否则设置为1

参数说明:

none "Referer" 为空

blocked "Referer"不为空,且不以http://或者https://开头,而是"Referer: xxxxx"这种形式

server_names "Referer"来源头部包含当前的server_names

注意:通过Referer实现防盗链比较基础,仅可以简单实现方式资源被盗用,构造Referer的请求很容易实现。