Openresty如何實(shí)現(xiàn)的網(wǎng)關(guān)權(quán)限控制

小編給大家分享一下Openresty如何實(shí)現(xiàn)的網(wǎng)關(guān)權(quán)限控制,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

榆中網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)建站,榆中網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為榆中上1000+提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站制作要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的榆中做網(wǎng)站的公司定做!

技術(shù)棧

本小節(jié)采用了以下的技術(shù)棧:

  • Openresty(lua+nginx)

  • MySQL

  • redis

  • cjson

驗(yàn)證流程

  • 用戶請(qǐng)求經(jīng)過(guò)nginx,nginx的openresty的模塊通過(guò)攔截請(qǐng)求來(lái)進(jìn)行權(quán)限判斷

  • openresty的access_by_lua_file模塊,進(jìn)行了一系列的判斷

    • 用戶的請(qǐng)求是否為白名單uri,如果為白名單uri,則直接通過(guò)驗(yàn)證,進(jìn)入下一個(gè)驗(yàn)證環(huán)節(jié)content_by_lua_file,這個(gè)環(huán)節(jié)直接打印一句話:“恭喜,請(qǐng)求通過(guò)。”

    • 如果用戶請(qǐng)求不為白名單url,則需要取出請(qǐng)求header中的token,如果請(qǐng)求的header不存在token,則直接返回結(jié)果401,無(wú)權(quán)限訪問(wèn)。

    • 如果用戶請(qǐng)求的uri的請(qǐng)求頭包含token ,則取出token,解密token取出用戶id

    • 根據(jù)取出的userid去查詢數(shù)據(jù)庫(kù)獲取該用戶的權(quán)限,如果權(quán)限包含了該請(qǐng)求的uri,請(qǐng)求可以通過(guò),否則,請(qǐng)求不通過(guò)。

  • 請(qǐng)求如果通過(guò)access_by_lua_file模塊,則進(jìn)入到content_by_lua_file模塊,該模塊直接返回一個(gè)字符串給用戶請(qǐng)求,在實(shí)際的開(kāi)發(fā)中,可能為路由到具體的應(yīng)用程序的服務(wù)器

驗(yàn)證流程圖如下所示:

Openresty如何實(shí)現(xiàn)的網(wǎng)關(guān)權(quán)限控制

vim /usr/example/example.conf ,加上以下的配置:

 location / {
    default_type "text/html";
    access_by_lua_file /usr/example/lua/api_access.lua;
    content_by_lua_file /usr/example/lua/api_content.lua;
  }

以上的配置表示,要不符合已有l(wèi)ocation路徑的所有請(qǐng)求,將走這個(gè)location為/  的路徑。符合這個(gè)location的請(qǐng)求將進(jìn)入 access_by_lua_file和 content_by_lua_file的模塊判斷。

vim /usr/example/lua/access_by_lua_file ,加上以下代碼:

local tokentool = require "tokentool"
local mysqltool = require "mysqltool"

 function is_include(value, tab)
   for k,v in ipairs(tab) do
      if v == value then
           return true
       end
    end
    return false
 end

local white_uri={"/user/login","/user/validate"}

--local user_id = ngx.req.get_uri_args()["userId"]
--獲取header的token值
local headers = ngx.req.get_headers() 
local token=headers["token"]
local url=ngx.var.uri
if ( not token) or (token==null) or (token ==ngx.null) then
  if is_include(url,white_uri)then

  else
    return ngx.exit(401)
  end  
else 
  ngx.log(ngx.ERR,"token:"..token)
  local user_id=tokentool.get_user_id(token)
  if (not user_id) or( user_id ==null) or ( user_id == ngx.null) then
      return ngx.exit(401)   
  end 

  ngx.log(ngx.ERR,"user_id"..user_id)
  local permissions={}
  permissions =tokentool.get_permissions(user_id)
  if(not permissions)or(permissions==null)or( permissions ==ngx.null) then
      permissions= mysqltool.select_user_permission(user_id)
      if permissions and permissions ~= ngx.null then
         tokentool.set_permissions(user_id,permissions)
      end
  end  
  if(not permissions)or(permissions==null)or( permissions ==ngx.null) then
     return ngx.exit(401)
  end 
  local is_contain_permission = is_include(url,permissions) 

  if is_contain_permission == true  then
     -- ngx.say("congratuation! you have pass the api gateway")
  else
      return ngx.exit(401) 
  end   
end

在上述代碼中:

  • is_include(value, tab),該方法判斷某個(gè)字符串在不在這個(gè)table中。

  • white_uri={“/user/login”,”/user/validate”} 是一個(gè)白名單的列表。

  • local headers = ngx.req.get_headers()從請(qǐng)求的uri的請(qǐng)求頭獲取token

  • is_include(url,white_uri)判斷該url是否為白名單url

  • local user_id=tokentool.get_user_id(token)根據(jù)token獲取該token對(duì)應(yīng)的用戶的user_id,在常見(jiàn)情況下,是根據(jù)token解析出user_id,但在不同的語(yǔ)言加密和加密token存在鹽值不一樣的情況,比較麻煩,所以我偷了個(gè)懶,直接存了redis,用戶登錄成功后存一下。

  • permissions =tokentool.get_permissions(user_id)根據(jù)user_id
    從redis獲取該用戶的權(quán)限。

  • permissions= mysqltool.select_user_permission(user_id)如果redis沒(méi)有存該用戶的權(quán)限,則從數(shù)據(jù)庫(kù)讀。

  • tokentool.set_permissions(user_id,permissions),將從數(shù)據(jù)庫(kù)中讀取的權(quán)限點(diǎn)存在reddis中。

  • local is_contain_permission = is_include(url,permissions),判斷該url 在不在該用戶對(duì)應(yīng)的權(quán)限列表中。

如果所有的判斷通過(guò),則該用戶請(qǐng)求的具有權(quán)限訪問(wèn),則進(jìn)入content_by_lua_file模塊,直接在這個(gè)模塊給請(qǐng)求返回“congratulations! you have passed the api gateway”。

vim  /usr/example/lua/api_content.lua ,添加以下內(nèi)容:

ngx.say("congratulations!"," you have passed ","the api gateway")  
----200狀態(tài)碼退出  
return ngx.exit(200)

驗(yàn)證演示

打開(kāi)瀏覽器訪問(wèn)http://116.196.177.123/user/login,瀏覽器顯示:

congratulations! you have passed the api gateway

/user/login這個(gè)url 在白名單的范圍內(nèi),所以它是可以通過(guò)權(quán)限驗(yàn)證的。

打開(kāi)瀏覽器訪問(wèn)http://116.196.177.123/user/sss,顯示以下內(nèi)容:

401 Authorization Required

openresty/1.11.2.4

在redis中添加一對(duì)key-value,key為token_forezp,value為1,即token_forezp對(duì)應(yīng)的用戶的id為1.

/usr/servers/redis-3.2.6

src/redis-cli

set token_forezp 1

初始化以下的sql腳本,即給用戶id為1的用戶關(guān)聯(lián)角色,角色并關(guān)聯(lián)權(quán)限:

INSERT INTO `permission` VALUES ('1', '/user/orgs');
INSERT INTO `role` VALUES ('1', 'user');
INSERT INTO `role_permission` VALUES ('1', '1', '1');
INSERT INTO `user` VALUES ('1', 'forezp');
INSERT INTO `user_role` VALUES ('1', '1', '1');

用postman請(qǐng)求,在請(qǐng)求頭中加入token,值為token_forezp,請(qǐng)求結(jié)果如下:

Openresty如何實(shí)現(xiàn)的網(wǎng)關(guān)權(quán)限控制

以上是“Openresty如何實(shí)現(xiàn)的網(wǎng)關(guān)權(quán)限控制”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

文章標(biāo)題:Openresty如何實(shí)現(xiàn)的網(wǎng)關(guān)權(quán)限控制
網(wǎng)站地址:http://muchs.cn/article28/ihcscp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、網(wǎng)站改版、響應(yīng)式網(wǎng)站、網(wǎng)站設(shè)計(jì)公司、移動(dòng)網(wǎng)站建設(shè)商城網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司