您好,登錄后才能下訂單哦!
小編給大家分享一下Openresty如何實現的網關權限控制,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
本小節采用了以下的技術棧:
用戶請求經過nginx,nginx的openresty的模塊通過攔截請求來進行權限判斷
openresty的access_by_lua_file模塊,進行了一系列的判斷
用戶的請求是否為白名單uri,如果為白名單uri,則直接通過驗證,進入下一個驗證環節content_by_lua_file,這個環節直接打印一句話:“恭喜,請求通過。”
如果用戶請求不為白名單url,則需要取出請求header中的token,如果請求的header不存在token,則直接返回結果401,無權限訪問。
如果用戶請求的uri的請求頭包含token ,則取出token,解密token取出用戶id
根據取出的userid去查詢數據庫獲取該用戶的權限,如果權限包含了該請求的uri,請求可以通過,否則,請求不通過。
請求如果通過access_by_lua_file模塊,則進入到content_by_lua_file模塊,該模塊直接返回一個字符串給用戶請求,在實際的開發中,可能為路由到具體的應用程序的服務器。
驗證流程圖如下所示:
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; }
以上的配置表示,要不符合已有location路徑的所有請求,將走這個location為/ 的路徑。符合這個location的請求將進入 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),該方法判斷某個字符串在不在這個table中。
white_uri={“/user/login”,”/user/validate”} 是一個白名單的列表。
local headers = ngx.req.get_headers()從請求的uri的請求頭獲取token
is_include(url,white_uri)判斷該url是否為白名單url
local user_id=tokentool.get_user_id(token)根據token獲取該token對應的用戶的user_id,在常見情況下,是根據token解析出user_id,但在不同的語言加密和加密token存在鹽值不一樣的情況,比較麻煩,所以我偷了個懶,直接存了redis,用戶登錄成功后存一下。
permissions =tokentool.get_permissions(user_id)根據user_id
從redis獲取該用戶的權限。
permissions= mysqltool.select_user_permission(user_id)如果redis沒有存該用戶的權限,則從數據庫讀。
tokentool.set_permissions(user_id,permissions),將從數據庫中讀取的權限點存在reddis中。
local is_contain_permission = is_include(url,permissions),判斷該url 在不在該用戶對應的權限列表中。
如果所有的判斷通過,則該用戶請求的具有權限訪問,則進入content_by_lua_file模塊,直接在這個模塊給請求返回“congratulations! you have passed the api gateway”。
vim /usr/example/lua/api_content.lua ,添加以下內容:
ngx.say("congratulations!"," you have passed ","the api gateway") ----200狀態碼退出 return ngx.exit(200)
打開瀏覽器訪問http://116.196.177.123/user/login,瀏覽器顯示:
congratulations! you have passed the api gateway
/user/login這個url 在白名單的范圍內,所以它是可以通過權限驗證的。
打開瀏覽器訪問http://116.196.177.123/user/sss,顯示以下內容:
401 Authorization Required
openresty/1.11.2.4
在redis中添加一對key-value,key為token_forezp,value為1,即token_forezp對應的用戶的id為1.
/usr/servers/redis-3.2.6 src/redis-cli set token_forezp 1
初始化以下的sql腳本,即給用戶id為1的用戶關聯角色,角色并關聯權限:
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請求,在請求頭中加入token,值為token_forezp,請求結果如下:
以上是“Openresty如何實現的網關權限控制”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。