背景
本文是一个环境搭建指导教程,目的指导开发人员在自己的项目中搭建动态路由+jwt token校验的网关服务。
第一部分 安装Openresty
第一步 安装Openresty依赖lib库
yum install pcre-devel openssl-devel gcc curl
第二步 安装、编译Openresty
在/opt/svr目录下
wget https://openresty.org/download/openresty-1.13.6.2.tar.gz
#解压
tar -zxvf openresty-1.13.6.2.tar.gz
#编译 默认安装目录:/usr/local/openresty
./configure
make & make install
第二部分 安装jwt
第一步 安装luajit、lua-json
luajit
#下载
wget -c http://luajit.org/download/LuaJIT-2.0.2.tar.gz
tar zxvf
# 指定安装目录/usr/local/luajit
make install PREFIX=/usr/local/luajit
echo "/usr/local/luajit/lib" > /etc/ld.so.conf.d/usr_local_luajit_lib.conf
Idconfig
#设置环境变量(etc/profile)
export LUAJIT_LIB=/usr/local/luajit/lib
export LUAJIT_INC=/usr/local/luajit/include/luajit-2.0
lua-json
wget http://www.kyne.com.au/~mark/software/download/lua-cjson-2.1.0.tar.gz
#解压
#修改MakeFile,指定到对应的luajit目录
#对应PREFIX、LUA_INCLUDE_DIR目录
PREFIX = /usr/local/luajit
LUA_INCLUDE_DIR = $(PREFIX)/include/luajit-2.0
make
make install
第二步 安装jwt
wget https://github.com/SkyLothar/lua-resty-jwt/releases/download/v0.1.11/lua-resty-jwt-0.1.11.tar.gz
cd /opt/openresty/lua-resty-jwt-0.1.11/lib
#将文件copy到/usr/local/openresty/nginx/jwt-lua目录下
cp -r * /usr/local/openresty/nginx/jwt-lua/
第三步 添加nginx-jwt-consul lua脚本
cp到/usr/local/openresty/nginx/jwt-lua下,新建nginx-jwt-consul.lua
local jwt = require "resty.jwt"
local cjson = require "cjson"
local secret = "**miffy**"
local M={}
function M.auth(claim_specs)
--ngx.log(ngx.INFO,"enter")
local auth_header = ngx.req.get_headers()
if auth_header == nil then
--ngx.log(ngx.WARN,"No Authorization header")
--ngx.say("{'code':'BIZ','type':'40301','msg':'No Header!'}")
--ngx.exit(ngx.HTTP_UNAUTHORIZED)
return M
end
local auth_token = auth_header['header-nome-Authorization']
local auth_appid = auth_header['HEADER-NOME-AppID']
if auth_appid ~= nil then
ngx.var.appid = auth_appid
end
if auth_token == nil then
return M
end
local jwt_obj = jwt:verify(secret, auth_token)
if jwt_obj.verified == false then
ngx.log(ngx.WARN, "Invalid token: ".. jwt_obj.reason)
local i,j = string.find(jwt_obj.reason,"claim expired at")
local k,h = string.find(jwt_obj.reason,"signature mismatch")
if i ~= nil and i > 0 then
ngx.say("{'code':'BIZ','type':'40302','msg':'Token expired!'}")
elseif k ~= nil and k > 0 then
ngx.say("{'code':'BIZ','type':'40301','msg':'Signature verify failed!'}");
else
ngx.say("{'code':'BIZ','type':'40303','msg':'"..jwt_obj.reason .."!'}")
end
ngx.exit(4001)
end
ngx.log(ngx.INFO,"<<<<".. cjson.encode(jwt_obj) .. " << ")
ngx.var.uid = jwt_obj.payload.sub
ngx.var.username = jwt_obj.payload.username
ngx.var.appid = jwt_obj.payload.aud
ngx.log(ngx.INFO,">>>>>".. ngx.var.uid .. " >> " .. ngx.var.appid)
end
return M
第三步 添加access-level-check.lua脚本
▽
local M={}
function M.accessCheck()
local uri = ngx.var.request_uri
local i,j = string.find(uri,"/user/(%d+)/")
if i ~= nil and i > 0 then
local uid = string.gsub(uri,"^/(.*)/user/(%d+)/(.*)","%2")
local tokenUid = ngx.var.uid
if tokenUid == nil then
ngx.say("{'code':'BIZ','type':'40001','msg':'User' access level needs valid pinuid'}");
ngx.exit(4001)
end
ngx.log(ngx.INFO, uid .. "..." .. tokenUid)
if uid ~= tokenUid then
ngx.say("{'code':'BIZ','type':'40001','msg':'User access level id in path mismatched with id in token'}");
ngx.exit(4001)
end
end
end
return M
第四步 配置openresty的nginx.conf
路径:/usr/local/openresty/nginx/conf
worker_processes auto;
worker_rlimit_nofile 100000;
pid logs/nginx.pid;
events {
worker_connections 2048;
multi_accept on;
use epoll;
}
lua_package_path "/usr/local/openresty/nginx/jwt-lua/?.lua;;";
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
第三部分 安装consul-template及配置
第一步 下载并安装consul-template
wget https://releases.hashicorp.com/consul-template/0.18.3/consul-template_0.18.3_linux_amd64.zip
unzip consul-template_0.18.3_linux_amd64.zip
mv consul-template /usr/local/bin/
第二步 编写consul模版脚本
nginx.conf.ctmpl
{{range services}} {{$name := .Name}} {{$service := service .Name}}
upstream {{$name}} {
zone upstream-{{$name}} 64k;
{{range $service}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;
{{else}}server 127.0.0.1:65535; # force a 502{{end}}
} {{end}}
server {
listen 8483 default_server;
underscores_in_headers on;
set $uid '';
set $username '';
set $appid '';
location / {
content_by_lua '
local str = [[{"code":"BIZ","type":"404","msg":"PAGE NOT PAGE"}]]
ngx.say(str)
ngx.exit(ngx.HTTP_UNAUTHORIZED)
';
}
{{range services}} {{$name := .Name}}
location ~ /{{$name}}/(user|admin|public) {
if ($request_uri ~ /{{$name}}/(.*)) {
set $subPath $1;
}
access_by_lua '
local jwt = require("nginx-jwt-consul")
jwt.auth()
local uid_check = require("resty.access-level-check")
uid_check.accessCheck()
';
proxy_set_header HEADER-NOME-UID $uid;
proxy_set_header HEADER-NOME-USER-NAME
$username;
proxy_set_header HEADER-NOME-AppID $appid;
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_pass http://{{$name}}/$subPath;
}
{{end}}
}
第三步 运行脚本
#仅运行一次,生成api.conf文件
consul-template -consul-addr 127.0.0.1:8500 -template="nginx.conf.ctmpl:/usr/local/openresty/nginx/conf/config.d/api.conf" -once
#生成api.conf文件,并持续监控consul节点的变化
consul-template -consul-addr 127.0.0.1:8500 -retry 30s -template="nginx.conf.ctmpl:/usr/local/openresty/nginx/conf/config.d/api.conf:/usr/local/openresty/nginx/sbin/nginx -s reload"
第四步 修改nginx.conf配置文件
include /usr/local/openresty/nginx/conf/config.d/api.conf;