Nginx系列:安全下载模块
阅读文本大概需要3分钟。
ngx_http_secure_link_module模块用于检查请求链接的真伪,保护资源免受未经授权的访问,限制链接的生命周期。
通过将请求中传递的校验和值与请求计算的值进行比较来验证请求链接的真实性。如果链接的生命周期有限并且时间已过,则该链接将被视为过时。
验证原理:
- 用户在客户端点击下载按钮,服务器收到请求后生成一个
下载地址
返回给客户端。 - 客户端使用这个生成的下载地址去请求资源,此时nginx去做校验,校验链接地址真伪和链接地址是否过期。如果链接地址是真的并且链接地址没有过期,就给客户端返回下载资源。
nginx验证和服务器生成密钥规则要一致,否则验证是不会通过的
该模块提供两种备选操作模式:
- 第一种模式
secure_link_secret
指令启用,用于检查请求链接的真实性以及保护资源免受未经授权的访问 - 第二种模式
secure_link
和secure_link_md5
指令启用,也用于限制链接生命周期。
更详细参考官网
http://nginx.org/en/docs/http/ngx_http_secure_link_module.html
0x01:配置模块语法
ngx_http_secure_link_module主要有以下三个语法
secure_link
Syntax: secure_link expression;
Default: —
Context: http, server, location
secure_link_md5
Syntax: secure_link_md5 expression;
Default: —
Context: http, server, location
secure_link_secret
Syntax: secure_link_secret word;
Default: —
Context: location
0x02:安装ngx_http_secure_link_module模块
- 首先检查nginx是否已安装模块
#nginx -V
结果如下,没有安装ngx_http_secure_link_module模块
输出nginx所有已安装模块,检查是否有ngx_http_secure_link_module,因为这个模块没有默认编译,在编译Nginx时,必须使用明确的配置参数
--with-http_secure_link_module
- 安装
执行以下命令
#先安装secure link 其实这个组件nginx本身就有,只不过是默认不安装罢了
./configure --prefix=/usr/local/nginx --user=nginx
--group=nginx --with-http_secure_link_module
--with-http_stub_status_module
执行mak编译nginx
make
make之后的操作需要注意,如果nginx第一次安装,直接执行make install即可
make install
如果单纯添加模块,不需要install,而是执行以下操作,将打过补丁的nginx二进制文件覆盖/usr/local/nginx/sbin/目录中的文件即可
#备份之前的nginx
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
#拷贝新的nginx到sbin目录
cp /nginx源码目录/objs/nginx /usr/local/nginx/sbin/
0x03: ngx_http_secure_link_module配置
在server节点增加以下location配置
location / {
root html;
#这里配置了2个参数一个是md5,一个是expires
secure_link $arg_md5,$arg_expires;
#md5的哈希格式为: expires+url+addr
#expires为时间戳单位s
#url为请求地址
#remote_addr为远程IP地址
#mysecure为密钥
secure_link_md5 "mysecure$secure_link_expires$uri$remote_addr";
if ($secure_link = "") {
#资源不存在或哈希比对失败
return 402;
}
if ($secure_link = "0") {
#时间戳过期
return 404;
}
if ($request_filename ~* ^.*?.(mp4)$){
#直接下载防止打开文件 格式: (mp4|txt|jpg)
add_header Content-Disposition 'attachment;';
}
}
#设置400,404的跳转
#在server节点
error_page 400 = 400.html; #跳转400页面
error_page 404 = 404.html; #跳转404页面
在html目录添加400.html和404.htmll两个界面
0x04:JAVA计算防盗链地址
需要使用到commons-codec-1.10.jar包,请自行下载
package com.alibaba.csp.sentinel.datasource.consul;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
/**
* 防盗链资源下载地址
*
*/
public class GenSourceDownloadPath {
final static String HTTP = "http://";
final static String ST = "?md5=";
final static String E = "&expires=";
final static String F = "/";
final static String WARN = "path参数最好带上 "/" ,例: "/abc.mp4" ";
final static String SERVER_IP = "127.0.0.1";
final static Long expires = 20L; //过期时间 秒
final static String secret = "mysecure"; //密钥
public static String execute(String path) {
if (path.indexOf(F) == -1) {
path = F + path;
System.out.println(WARN);
}
// +n代表n秒后地址失效
String time = String.valueOf(System.currentTimeMillis() / 1000 + expires);
// $secure_link_expires$uri$remote_addr
String md5Str = secret + time + path + SERVER_IP;
byte[] md5byte = DigestUtils.md5(md5Str);
String base64 = Base64.encodeBase64URLSafeString(md5byte);
return HTTP + SERVER_IP + path+ ST + base64 + E + time;
}
public static void main(String[] args) {
System.out.println(execute("my.conf"));
}
}
现在html目录存放一个图片文件my.conf,该文件是需要访问演示的文件
执行GenSourceDownloadPath生成一个访问的URL:
http://127.0.0.1/my.conf?md5=YO4diAmlVa8NfHlMBCMFaw&expires=1598071052
执行访问
如果没有带参数访问
超过20s访问,不在有权限访问
备注:
如果按官方秘密mysecure放在最后,需加一个空格与参数分隔
在使用java计算时也需要多加一个空格
- centos6.5虚拟机安装后,没有iptables配置文件
- 温故而知新:设计模式之Builder
- 温故而知新:设计模式之单件模式(Singleton)
- sudo命令使用的几个场景
- .NET Core系列 : 2 、project.json 这葫芦里卖的什么药
- 关闭与恢复visual studio实时调试器
- linux系统下的权限知识梳理
- c#如何启动/干掉/查找 进程
- Android中Application的应用
- 孟昭莉博士:大数据大道之行
- .NET Core系列 :3 、使用多个项目
- 完整部署CentOS7.2+OpenStack+kvm 云平台环境(2)--云硬盘等后续配置
- 完整部署CentOS7.2+OpenStack+kvm 云平台环境(3)--为虚拟机指定固定ip
- ubuntu系统升级记录
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 03Python List不得不知的操作之改、查
- 04Python基础之字符串Str
- 05Python元组tuple的个性
- Tkinter Canvas
- Python实现最小二乘法
- 一个简单的例子学明白用Python插值
- python 类class基础简明笔记
- 数据离散化及其KMeans算法实现的理解
- [tensorflow损失函数系列]sparse_softmax_cross_entropy_with_logits
- 怎样将Anaconda设置为国内的镜像
- Python实现KMeans算法
- Python面向对象编程
- HTML和CSS常见问题整理
- Nginx Linux详细安装部署教程
- Linux基础知识(1)