背景需求

有的业务场景需要nginx直接反向代理附件目录,但是直接在公网访问是不安全的,研发侧也不愿意从后端生成附件访问链接,
这个方案的实现基于上述考虑形成一个内部使用的一个下载连接,以避免 非内部人员,渗透,漏扫和不知名来源的访问。

实现步骤

1. 安装openrestry
3. 一个下载的文件任意即可
4. 和 开发 约定一个加盐的固定值
5. sha1加密(盐+时间戳)

URL样例:
	https://域名A/文件名?signature=加盐后的sha1值&t=时间戳

lua代码及openrestry的配置文件内容

download-auth.lua

-- 设置 OpenResty 的库路径 
package.path = "/mnt/apps/openresty/lualib/?.lua;" .. package.path

-- 动态变量
local key = "加盐的固定值"
-- 设置超时时间 60*60 一个小时
local overtime = 3600 
-- 加载 resty.sha1 模块
local resty_sha1 = require "resty.sha1"
local resty_string = require "resty.string"

-- 从 Nginx 变量中获取 SHA1 值和时间戳
local signature = ngx.var.arg_signature
local ngx_timestamp = ngx.var.arg_t

--获取当前的时间戳
local now_timestamp = os.time()

-- 要加密的字符串 盐值+10位数的时间戳
local combined_string = key..ngx_timestamp

-- 使用 resty.sha1 计算 SHA1 哈希值
local sha1 = resty_sha1:new()
sha1:update(combined_string)
local digest = sha1:final()
local sha1_hash = resty_string.to_hex(digest)

-- ngx.say("SHA1 Hash: " .. sha1_hash)

-- 判断传入的时间戳是否超时 超时返回505 
if ngx_timestamp then
  local time_interval = now_timestamp - ngx_timestamp
  if time_interval > overtime  then
    return ngx.exit(505)
  end 
end

if signature and ngx_timestamp then
   
     -- 如果 关键值没有匹配上就返回503 状态码
  if not (signature == sha1_hash) then
--    ngx.log(ngx.ERR,"signature: "..signature.."  sha1_hash: "..sha1_hash)
    return ngx.exit(503)
  -- ngx.say("signature: "..signature.."  t:"..ngx_timestamp)
  end
else
     -- 都没有匹配上就返回501 状态码
  -- ngx.say("Service Temporarily Unavailable")
  return ngx.exit(501)
end

openrestry配置文件内容

server {
        listen       80;
        server_name  域名A;
        return 302 https://$server_name$request_uri; #http跳转https
   }
   server {
        listen       443 ssl;
        server_name  域名A;
        index index.html;
        client_body_buffer_size 128k;
        client_max_body_size    300m;

        ssl_certificate     cert/public.pem;
        ssl_certificate_key cert/public.key;
        ssl_session_timeout 5m;
        ssl_ciphers         ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;

        location / {
                access_by_lua_file lua脚本的位置; 
                alias 文件的存放目录;
                index index.html;
        }
   }

相关效果截图

image-20241114144822396.png
image-20241114144948035.png

sha1 生成工具类

百度搜索 在线sha1 点击任意一个都可以在线实现转换,我这边提供一个 python的工具类,喜欢可以自行拿走

image-20241114143421368.png

# encoding: utf-8

import hashlib

def generate_sha1(combined_value):
    # 创建 SHA-1 哈希对象
    sha1_hash = hashlib.sha1()

    # 更新哈希对象
    sha1_hash.update(combined_value.encode('utf-8'))

    # 获取十六进制表示的哈希值
    hash_result = sha1_hash.hexdigest()

    print(f"SHA-1 哈希值: {hash_result}")
    return hash_result


if __name__ == '__main__':
    salt_value='盐值'
    t='10位数时间戳'
    combined_value=salt_value+t
    generate_sha1(combined_value)