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;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355

推荐阅读更多精彩内容