OpenResty(nginx+lua+resty-http)实现访问鉴权

OpenResty(nginx+lua+resty-http)实现访问鉴权

最近用BI框架解决了一些报表需求并生成了公开链接,现在CMS开发人员打算将其嵌入到业务系统中,结果发现公开链接一旦泄露任何人都可以访问,需要实现BI系统报表与业务系统同步的权限控制。但是目前使用的BI框架并不支持这样的功能,如果自己修改BI系统去实现这样的功能开发成本太高。

基于这样的背景下,我想到了使用Nginx网关来实现目标页面的鉴权。结果发现了OpenResty,下面我将实操过程分享给大家。这次使用了PowerBI和其他BI系统,所测试的服务器为Windows Server系统。其他系统的具体操作细节会有所区别,下面我只以Windows系统为例进行演示。

OpenResty 简介与安装

OpenResty 是一个基于 Nginx 和 LuaJIT 的动态 web 平台。它通过在 Nginx 中集成 LuaJIT,允许在 Nginx 服务器上运行 Lua 脚本,增加了 Nginx 的灵活性和可扩展性。

官网下载页:http://openresty.org/en/download.html

首先下载openresty-1.21.4.3-win64.zip 并解压

原版Nginx带有nginx-service.exe可以很方便的将Nginx注册为系统服务。

下面我复制原版Nginx中的nginx-service.exenginx-service.xml文件 到 新解压的 E:\soft\openresty-1.21.4.3-win64目录中。

若以前的Nginx已经注册服务可以使用以下命令先取消注册:

nginx-service.exe uninstall nginx

然后修改nginx-service.xml文件为如下内容:

xml 复制代码
<service>
	<!-- 服务名 -->
	<id>nginx</id>
	<!-- 显示名称 -->
	<name>Nginx Service</name>
	<!-- 描述 -->
	<description>High Performance Nginx Service</description>
	<logpath>E:\soft\openresty-1.21.4.3-win64\logs</logpath>
	<log mode="roll-by-size">
		<sizeThreshold>10240</sizeThreshold>
		<keepFiles>8</keepFiles>
	</log>
	<executable>E:\soft\openresty-1.21.4.3-win64\nginx.exe</executable>
	<startarguments>-p E:\soft\openresty-1.21.4.3-win64</startarguments>
	<stopexecutable>E:\soft\openresty-1.21.4.3-win64\nginx.exe</stopexecutable>
	<stoparguments>-p E:\soft\openresty-1.21.4.3-win64 -s stop</stoparguments>
</service>

然后执行即可将新安装的OpenResty 的Nginx注册为服务:

nginx-service.exe install nginx

可以将上述过程用bat脚本自动化,首先创建文件nginx-service-template.xml,内容如下:

xml 复制代码
<service>
	<id>nginx</id>
	<name>Nginx Service</name>
	<description>High Performance Nginx Service</description>
	<logpath>{{dir}}\logs</logpath>
	<log mode="roll-by-size">
		<sizeThreshold>10240</sizeThreshold>
		<keepFiles>8</keepFiles>
	</log>
	<executable>{{dir}}\nginx.exe</executable>
	<startarguments>-p {{dir}}</startarguments>
	<stopexecutable>{{dir}}\nginx.exe</stopexecutable>
	<stoparguments>-p {{dir}} -s stop</stoparguments>
</service>

然后创建bat脚本安装nginx服务.bat

bash 复制代码
@echo off
setlocal enabledelayedexpansion

set "path=%~dp0"
set "path=%path:~0,-1%"
>"nginx-service.xml" (
   for /f "delims=" %%i in ('type "nginx-service-template.xml"') do (
      set "line=%%i"
      set "line=!line:{{dir}}=%path%!"
      echo(!line!
   )
)
nginx-service.exe uninstall nginx
nginx-service.exe install nginx

echo "Install complate"
pause

然后执行命令即可一键安装新的Nginx服务:

更新nginx服务.bat

注意:以上脚本都在openresty-1.21.4.3-win64的安装目录下,一键生成配置并安装服务。

resty.http的安装

我们的鉴权脚本需要http请求目标服务,但是resty.http并未集成到openresty中,所以需要我们自行下载。

下载地址为:https://github.com/ledgetech/lua-resty-http

将lib/resty目录下的三个lua脚本复制到openresty-1.21.4.3-win64\lualib\resty目录中。

这样我们就满足在lua脚本中发起http请求的基本条件。

lua鉴权脚本编写

首先我们实现一个基本的鉴权脚本:

lua 复制代码
local token = ngx.var.arg_token
if not token then
	ngx.exit(400)
end
if token ~= "123" then
	ngx.exit(401)
end

上述脚本获取get请求的token参数,判断值是否为123,不是123则鉴权不通过返回401。

下面我们为了实现与业务系统的权限一致,需要询问业务系统传入的token是否有效,这时就需要使用resty.http

lua 复制代码
local token = ngx.var.arg_token
if not token then
	ngx.exit(400)
end
local http = require "resty.http"
local httpc = http.new()
local url = "https://业务系统提供的接口地址?token="..token
local res, err = httpc:request_uri(url, {
    method = "GET",
    headers = {
		["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.289 Safari/537.36",
	},
	ssl_verify = false
})
if not res then
    ngx.exit(402)
end
if res.body ~= "success" then
    ngx.exit(403)
end

以上脚本根据业务系统是否返回success,决定鉴权是否通过。

请求中使用ssl_verify = false是因为 Nginx 服务器无法验证服务器的 SSL证书,因为它没有正确配置必要的根证书,相对给Nginx配置根证书,直接取消验证更简单一些。

resty.http更多用法:https://github.com/ledgetech/lua-resty-http#request

Nginx配置鉴权脚本

下面我们配置Nginx的核心脚本:

nginx 复制代码
http {
	map $http_upgrade $connection_upgrade {  
		default upgrade;
		''      close;
	}
	...
	
    server {
        listen       80;
        server_name  localhost;
		location ^~ /xxx/websocket {
			proxy_pass http://localhost:9999;
			proxy_http_version 1.1;
			proxy_set_header Upgrade $http_upgrade;
			proxy_set_header Connection $connection_upgrade;
		}
		location /xxx/ {
			rewrite_by_lua_file lua/auth.lua;
			proxy_pass http://localhost:9999;
			proxy_hide_header X-Frame-Options;
			proxy_hide_header Content-Security-Policy;
			proxy_hide_header X-Xss-Protection;
			add_header Access-Control-Allow-Origin *;
		}
    }
	resolver 8.8.8.8;
}

上面最核心的配置是rewrite_by_lua_file lua/auth.lua;

注意:resolver是必须配置的,用于配置DNS服务器,否则auth.lua脚本的HTTP请求无法正确获取响应。

rewrite_by_lua_file 指定了前面编写的鉴权脚本lua/auth.lua,相对openresty所在的根目录下。

附录

lua读取请求参数的其他用法

lua 复制代码
--获取请求header
local reqHeaders = ngx.req.get_headers();
--读取cookie中的pcip值
local pcip = ngx.var.cookie_pcip;
--获取请求URI
local requestUri = ngx.var.request_uri;
--获取请求域名
local requestHost = ngx.var.host;
----获取请求方法类型GET POST
local reqType= ngx.var.request_method;

openresty的基本框架

openresty中文站:http://openresty.org/cn/

相关推荐
红黑色的圣西罗13 小时前
Lua 怎么解决闭包内存泄漏问题
开发语言·lua
JustCouvrir18 小时前
macOS|前端工程部署到Nginx服务器
服务器·前端·nginx
AlbertS19 小时前
使用 Let’s Encrypt 获取免费SSL证书
nginx·免费·centos7·ssl证书·let’s encrypt
航月19 小时前
FTP、ISCSI、CHRONY、DNS、NFS、DOCKER、MARIADB、NGINX、PHP、CA各服务开启方法
nginx·docker·mariadb
诗这样的1 天前
【需求变更】使用 Redis 和 Lua 脚本实现变更后方案编号的生成
java·redis·缓存·微服务·lua·需求分析
gopher95111 天前
lua 运算符和控制语句
开发语言·lua
IT-民工211101 天前
nginx监控指标有哪些
运维·nginx
陌路物是人非1 天前
docker对nginx.conf进行修改后页面无变化或页面报错
nginx·docker
草明2 天前
Nginx 做反向代理,一个服务优先被使用,当无法提供服务时才使用其他的备用服务
运维·nginx·github
不喝水的鱼儿2 天前
【LuatOS】修改LuatOS源码为PC模拟器添加高精度时间戳库timeplus
lua·时间戳·luatos