Openresty 搭建jwt+consul-template动态发现

背景

本文是一个环境搭建指导教程,目的指导开发人员在自己的项目中搭建动态路由+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;

你可能感兴趣的:(Openresty 搭建jwt+consul-template动态发现)