Nginx内置lua版OpenResty拦截转发请求Redis等操作

发布时间 2023-08-24 13:54:14作者: Ideaway

Nginx内置lua版OpenResty拦截转发请求Redis等操作

1 下载并安装OpenResty

http://openresty.org/cn/download.html

2 下载 lua-resty-http-0.17.1 库 以让openresty的lua支持外部http访问能力

lua-resty-http-0.17.1

1 下载 lua-resty-http-0.17.1

2 然后将文件中lua-resty-http-0.17.1\lib\resty 下面的 http.lua放到openresty-1.21.4.2-win64\lualib\resty文件夹中

3 nginx.conf文件位于openresty-1.21.4.2-win64/conf文件夹中,而lua-resty-http库位于openresty-1.21.4.2-win64/lualib/resty目录中,按照以下方式设置lua_package_path指令:

http {
    lua_package_path "./../lualib/?.lua;;";
    ...
}

使用了相对路径./../lualib/?.lua来指定lua-resty-http库的路径。./..表示上一级目录,然后进入lualib目录,然后使用?.lua通配符来匹配所有的Lua文件

3 编写代码逻辑流程

在openresty-1.21.4.2-win64\luaCode文件中新建filterLogin.lua文件,并书写处理逻辑

local redis = require "resty.redis"

local function handleRequest()
    -- 连接到 Redis 服务器
    local red = redis:new()
    local ok, err = red:connect("127.0.0.1", 6379)
    if not ok then
        ngx.log(ngx.ERR, "failed to connect to Redis: ", err)
        return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
    end

    -- 选择 Redis 的 DB1
    ok, err = red:select(1)
    if not ok then
        ngx.log(ngx.ERR, "Failed to select Redis DB: ", err)
        return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
    end

    -- 判断请求 URL 是否包含 "ssologin" 或 "authToken"
    local request_uri = ngx.var.request_uri
    local auth_token = ngx.var.http_authtoken
    local body_data = ngx.req.get_body_data()

    -- 从 Redis 中获取指定 key 的值
    local client_ip = ngx.var.remote_addr
    local client_ip_str = "ip" .. client_ip
    local value, err = red:get(client_ip_str)

    if request_uri:find("ssologin") or request_uri:find("authToken") or request_uri:find("keepLogin") or request_uri:find("websocket")  or (body_data and body_data:find("authToken")) then
        -- 放行请求
        if request_uri:find("extensionAuthority") then
            -- 将值重新放入 Redis 并设置有效期为 30 分钟
            ok, err = red:setex(client_ip_str, 1800, value)
        end
        return
    end



    if not value then
        ngx.log(ngx.ERR, "failed to get value from Redis: ", err)
        return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
    end

    -- 判断值是否存在并进行相应处理
    if value == ngx.null then
        -- 转发到 www.baidu.com
        -- return ngx.redirect("http://192.9.100.73:31100/operation/keepLogin/sendLoginOut?ip=" .. client_ip_str)
        -- 构建GET请求的URL
        local http = require("resty.http")

        local httpc = http.new()
        local url = "http://192.9.100.73:31100/operation/keepLogin/sendLoginOut?ip=" .. ngx.escape_uri(client_ip_str)

        local res, err = httpc:request_uri(url, {
            method = "GET",
        })

        if not res then
            ngx.log(ngx.ERR, "failed to send GET request: ", err)
            return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
        end

        if res.status == ngx.HTTP_OK then
            local body = res.body
            -- 处理响应
            -- body 为响应体内容
            -- ...
        else
            ngx.log(ngx.ERR, "failed to send GET request: ", res.status)
            return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
        end
    else
        -- 放行请求
        -- 将值重新放入 Redis 并设置有效期为 30 分钟
        ok, err = red:setex(client_ip_str, 60, value)
        if not ok then
            ngx.log(ngx.ERR, "failed to set value in Redis: ", err)
        end
        return
    end

    -- 关闭与 Redis 的连接
    local ok, err = red:set_keepalive(10000, 100)
    if not ok then
        ngx.log(ngx.ERR, "failed to set Redis keepalive: ", err)
    end
end
handleRequest()

4 nginx.conf里面增加代码处理进行转发处理

openresty-1.21.4.2-win64/conf文件夹中nginx.conf里面进行转发处理

http {
    include       mime.types;
    default_type  application/octet-stream;
    lua_shared_dict redis_cache 100m;
    include mime.types;
    client_max_body_size 200m;
    # 引入lua-resty-http-0.17.1以让openresty的lua支持外部http访问能力
	lua_package_path "./../lualib/?.lua;;";

    sendfile        on;

    keepalive_timeout  65;

    #自定义变量
    #FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    fastcgi_buffer_size 128k;
    fastcgi_buffers 8 128k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    map $http_user_agent $basePath {
      default '';
    }
    map $http_user_agent $baseUrl {
      default '';
    }

    server {
            listen 31100;

            location ^~ /operation/ {
                 proxy_set_header Host $host;
                 proxy_set_header X-Real-IP $remote_addr;
                 # 让后续可以获取代理前的请求原地址
                 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                 proxy_set_header Connection 'upgrade';
                 proxy_set_header Upgrade $http_upgrade;
                 proxy_pass http://192.9.100.73:7013/;
                 # 表示走此文件的代理逻辑
                 access_by_lua_file ./luaCode/filterLogin.lua;
            }

            location ^~ /zuul/ {
                  proxy_set_header Host $host;
                  proxy_set_header X-Real-IP $remote_addr;
                  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                  proxy_set_header Connection 'upgrade';
                  proxy_set_header Upgrade $http_upgrade;
                  proxy_pass http://192.9.100.73:7012/;
                  # 表示走此文件的代理逻辑
                  access_by_lua_file ./luaCode/filterLogin.lua;
            }
			
			location ^~ /service/ {
                  proxy_set_header Host $host;
                  proxy_set_header X-Real-IP $remote_addr;
                  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                  proxy_set_header Connection 'upgrade';
                  proxy_set_header Upgrade $http_upgrade;
                  # 表示走此文件的代理逻辑
                  proxy_pass http://192.9.100.73:7080/;
            }
        }
}