OpenResty,Nginx实现接口验签与黑名单控制

介绍

nginx与openresty是两种优秀知名的7层负载均衡软件,nginx以其出色的性能和稳定性成为首选,而openresty则是在Nginx基础上构建的,支持嵌入Lua语言,大幅提升了开发效率。

安装OpenResty

功能实现

验签直接返回响应体

  • 打开nginx.conf文件编写脚本(使用hmac对原文生成hash值再取base64编码)
server {
        listen       80;
        server_name  localhost;
		#对外接口验签
		location /api {
		    default_type "application/json";
		    content_by_lua_block {
		        -- table是否包含指定元素方法
		        function arr_include(tab, value)
                    for k,v in pars(tab) do
                      if v == value then
                          return true
                      end
                    end
                    return false
                end

		        local headers = ngx.req.get_headers();
				local token = headers["token"];
				-- 无token
				if (token == nil) then
                    ngx.say(string.format("{\"success\":false,\"msg\":\"%s\"}", "token为空"));
                    return;
				end
				-- 黑名单
                local guestIp = headers["X-Real-IP"] or headers["X-Forwarded-For"] or ngx.var.remote_addr;
                ngx.say(string.format("请求ip:%s", guestIp));
                local blacks = {"127.0.0.1", "10.190.75.139"};
                if (arr_include(blacks, guestIp)) then
                    ngx.say(string.format("{\"success\":false,\"msg\":\"%s\"}", "黑名单禁止访问"));
                    return;
                end
				-- 验签-读取请求体
				ngx.req.read_body();
				local reqBody = ngx.req.get_body_data();
				ngx.say(string.format("请求体:%s", reqBody));
			    -- 开始验签
                local key = "A7409BB67B472E6CC7EF17C49784A6B8";
                local digest = ngx.encode_base64(ngx.hmac_sha1(key, reqBody));
                ngx.say(string.format("nginx签名值:%s", digest));
                if (digest == token) then
                    ngx.say(string.format("{\"success\":true,\"msg\":\"%s\"}", "校验通过"));
                else
                    ngx.say(string.format("{\"success\":false,\"msg\":\"%s\"}", "验签失败"));
                end
			}
		}
    }
  • 启动nginx.exe

  • 客户端hmac哈希签名
    通过sha1哈希算法与密钥生成签名值
    在这里插入图片描述

  • 注释黑名单代码并且nginx -s reload后,调用接口测
    在这里插入图片描述
    在这里插入图片描述

  • 启用黑名单代码后,调用接口测试
    在这里插入图片描述
    黑名单功能也可以将黑名单放入redis,通过OpenResty编写lua脚本从redis获取黑名单ip来实现

验签通过后转发到上游服务

  • 介绍
    在上面的例子实现了验签后直接返回结果,但真实应用的时候一般是验签通过后转发到上游的业务应用,这时候我们的脚本得稍微进行改造,使用access_by_lua_block。
  • 代码实现
server {
        listen       80;
        server_name  localhost;
        location / {
		    default_type "text/html";
            content_by_lua 'ngx.say("<html><p>nginx start by lua<p><html>")';
        }
		#对外接口验签
		location /api {
		    default_type "application/json";
		    access_by_lua_block {
		        -- table是否包含指定元素方法
		        local function arr_include(tab, value)
                    for k,v in pairs(tab) do
                      if v == value then
                          return true
                      end
                    end
                    return false
                end

		        local headers = ngx.req.get_headers();
				local token = headers["token"];
				-- 无token
				if (token == nil) then
				    ngx.status = 403;
                    ngx.say(string.format("{\"success\":false,\"msg\":\"%s\"}", "token为空"));
                    return ngx.exit(403);
				end
				-- 黑名单
                local guestIp = headers["X-Real-IP"] or headers["X-Forwarded-For"] or ngx.var.remote_addr;
                local blacks = {"10.190.75.139"};
                if (arr_include(blacks, guestIp)) then
                    ngx.status = 403;
                    ngx.say(string.format("{\"success\":false,\"msg\":\"%s\"}", "黑名单禁止访问"));
                    return ngx.exit(403);
                end
				-- 验签-读取请求体
				ngx.req.read_body();
				local reqBody = ngx.req.get_body_data();
			    -- 开始验签
                local key = "A7409BB67B472E6CC7EF17C49784A6B8";
                local digest = ngx.encode_base64(ngx.hmac_sha1(key, reqBody));
                if (digest ~= token) then
                    ngx.status = 403;
                    ngx.say(string.format("{\"success\":false,\"msg\":\"%s\"}", "验签失败"));
                    return ngx.exit(403);
                end
			}
			proxy_pass http://localhost/backend;
		}

		location /backend {
		    default_type "application/json";
		    content_by_lua_block {
		        ngx.say(string.format("{\"success\":true,\"msg\":\"%s\"}", "校验通过"));
                return ngx.exit(200);
		    }
		}
    }
  • nginx -s reload后测试
    在这里插入图片描述
    在这里插入图片描述

相关推荐

  1. 【PHP】PHP实现RSA加密,解密,加

    2024-04-12 06:08:07       43 阅读
  2. 自定义对外开放接口的加解密和签名、

    2024-04-12 06:08:07       19 阅读
  3. 基于NDK的方式实现APP重签名校验方案

    2024-04-12 06:08:07       38 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-12 06:08:07       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-12 06:08:07       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-12 06:08:07       20 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-12 06:08:07       20 阅读

热门阅读

  1. HTTP状态码大全:常见状态码一网打尽

    2024-04-12 06:08:07       14 阅读
  2. 构建CICD

    2024-04-12 06:08:07       16 阅读
  3. Binary Tree Mock

    2024-04-12 06:08:07       18 阅读
  4. 微服务支持平台--限流算法

    2024-04-12 06:08:07       13 阅读
  5. vue3 问递归算法中解决ajax访问题

    2024-04-12 06:08:07       15 阅读
  6. Bash将输出同时重定向到标准输出stdout和文件

    2024-04-12 06:08:07       15 阅读
  7. Python防止打包后的exe重复执行

    2024-04-12 06:08:07       10 阅读
  8. 从零开始实现一个RPC框架(五)

    2024-04-12 06:08:07       11 阅读
  9. 「PHP系列」PHP面向对象详解

    2024-04-12 06:08:07       14 阅读
  10. 5G智慧港口简介(二)

    2024-04-12 06:08:07       12 阅读