Nginx的模块http_secure_link_module主要实现下面两个功能:

(1)指定并允许检查请求的链接的真实性以及保护资源免遭未经授权的访问
(2)限制链接生效周期

http_secure_link_module模块说明

编译时新增参数

./configure –with-http_secure_link_module

官方说明文档:

http://nginx.org/en/docs/http/ngx_http_secure_link_module.html

配置

 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
server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

    location / {

       secure_link $arg_md5,$arg_expires;
       secure_link_md5 "$secure_link_expires$uri test";

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

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


        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}

生成url脚本:

1
2
3
4
5
6
7
8
9
#!/bin/bash
servername="10.10.0.101:60080"
download_file_path="/a.txt"
expires=$(date -d "+300 seconds" +%s)  #定义过期时间为300秒
#expires=1681870908
secret_key="test"   #自定义的加密串,和nginx的配置文件中加密串相同
 
res=$(echo -n "${expires}${download_file_path} ${secret_key}"|openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d =)  #生成MD5值
echo "http://${servername}${download_file_path}?md5=${res}&expires=${expires}"  #打印下载链接

生成的url例子:

1
http://10.10.0.101:60080/a.txt?md5=XZAhLDP7XupZEYKswgvxRQ&expires=1681870908

生成url的java实现:

 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
39
40
41
42
43
44
45
46
47
48
49
50
51
import org.junit.Test;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Base64;

public class UrlTest {

    public static long getExpires(long sec) {
        // 获取当前时间,并加上 300 秒
        Instant now = Instant.now();
        Instant future = now.plus(sec, ChronoUnit.SECONDS);

        // 将时间转换为 UNIX 时间戳(单位:秒)
        long expires = future.getEpochSecond();

        return expires;
    }

    public static String getHash(String input) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        // 计算 MD5 哈希值
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] hash = md.digest(input.getBytes("UTF-8"));

        // 将哈希值进行 Base64 编码
        String base64Str = Base64.getEncoder().encodeToString(hash);

        // 进行字符替换
        String result = base64Str.replace("+", "-").replace("/", "_").replaceAll("=","");

        return result;
    }

    @Test
    public void genNginxSecureUrl() throws NoSuchAlgorithmException, UnsupportedEncodingException {
        long sec = 300;
        String path = "/a.txt";
        String key = "test";

        long expires = getExpires(sec);
//        String input = "1681870908/a.txt test";
        String input = String.valueOf(expires) + path + " " + key;
        String md5 = getHash(input);
        System.out.println(expires);
        System.out.println(md5);
//        http://127.0.0.1/a.txt?md5=jQ0kh5iqSPVKweEQYiho7Q&expires=1681872851
    }
}