您好,登錄后才能下訂單哦!
這篇文章主要介紹了Openresty中RBAC、sql和redis模塊工具類的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
RBAC(Role-Based Access Control,基于角色的訪問控制),用戶基于角色的訪問權限控制。簡單地說,一個用戶擁有若干角色,每一個角色擁有若干權限。這樣,就構造成“用戶-角色-權限”的授權模型。在這種模型中,用戶與角色之間,角色與權限之間,一般都是多對多的關系。如圖所示:
在本案例中,采用的就是這種權限設計的方式。具體的sql語句腳本如下:
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT , `name` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=latin1 COLLATE=latin1_swedish_ci AUTO_INCREMENT=2 ROW_FORMAT=COMPACT ; CREATE TABLE role( `id` int(11) NOT NULL AUTO_INCREMENT , `name` varchar(255) CHARACTER SET latin5 NULL DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=latin1 COLLATE=latin1_swedish_ci AUTO_INCREMENT=2 ROW_FORMAT=COMPACT ; CREATE TABLE permission( `id` int(11) NOT NULL AUTO_INCREMENT , `permission` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=latin1 COLLATE=latin1_swedish_ci AUTO_INCREMENT=3 ROW_FORMAT=COMPACT ; CREATE TABLE user_role( `id` int(11) NOT NULL AUTO_INCREMENT , `user_id` int(11) NULL DEFAULT NULL , `role_id` int(11) NULL DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=latin1 COLLATE=latin1_swedish_ci AUTO_INCREMENT=2 ROW_FORMAT=COMPACT ; CREATE TABLE role_permission( `id` int(11) NOT NULL AUTO_INCREMENT , `role_id` int(11) NULL DEFAULT NULL , `permission_id` int(11) NULL DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=latin1 COLLATE=latin1_swedish_ci AUTO_INCREMENT=3 ROW_FORMAT=COMPACT ;
初始化以下的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');
在本案例中,需要根據user表中的Id獲取該Id對應的權限。首先根據userId獲取該用戶對應的角色,再根據根據該角色獲取相應的權限,往往一個用戶具有多個角色,而角色又有多個權限。比如查詢userId為1 的用戶的權限的sql語句如下:
SELECT a.id,a.permission from permission a ,role_permission b,role c,user_role d,user e WHERE a.id=b.permission_id and c.id=b.role_id and d.role_id=c.id and d.user_id=e.id and e.id=1"
在Openresty中怎么連接數據庫,怎么查詢sql語句,在之前的文章已將講述過了。根據用戶id獲取用戶的權限的功能是一個使用率極高的功能,所以考慮將這個功能模塊化。
vim /usr/example/lualib/sql_tool.lua ,編輯加入以下的代碼:
local mysql = require("resty.mysql") local function close_db(db) if not db then return end db:close() end local function select_user_permission(user_id) local db, err = mysql:new() if not db then ngx.say("new mysql error : ", err) return end db:set_timeout(1000) local props = { host = "127.0.0.1", port = 3306, database = "test", user = "root", password = "123" } local res, err, errno, sqlstate = db:connect(props) if not res then ngx.say("connect to mysql error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate) close_db(db) end local select_sql = "SELECT a.id,a.permission from permission a ,role_permission b,role c,user_role d,user e WHERE a.id=b.permission_id and c.id=b.role_id and d.role_id=c.id and d.user_id=e.id and e.id="..user_id res, err, errno, sqlstate = db:query(select_sql) if not res then ngx.say("select error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate) return close_db(db) end local permissions={} for i, row in ipairs(res) do for name, value in pairs(row) do if name == "permission" then table.insert(permissions, 1, value) end end end return permissions end local _M = { select_user_permission= select_user_permission } return _M
在上面的代碼中,有一個select_user_permission(user_id)方法,該方法根據用戶名獲取該用戶的權限。查出來存在一個table 類型的 local permissions={}中。
vim /usr/example/example.conf 加上以下的代碼:
location ~ /sql_tool{ default_type 'text/html'; content_by_lua_file /usr/example/lua/test_sql_tool.lua; }
在瀏覽器上訪問http://116.196.177.123/sql_tool,瀏覽器顯示如下的內容:
/user/orgs
在之前的文章講述了如何使用Openresty連接redis,并操作redis。 這小節將講述如何使用openresty連接redis,并寫幾個方法,用于存儲用戶的token等,并將這些信息模塊化,主要有以下幾個方法:
close_redis(red) 通過連接池的方式釋放一個連接
connect() 連接redis
has_token(token) redis中存在token 與否
get_user_id(token) 根據token獲取用戶id
set_permissions(user_id,permissions) 根據userid設置權限
get_permissions(user_id)根據userid獲取權限
vim /usr/example/lualib/tokentool.lua 編輯一下內容:
module("tokentool", package.seeall) local redis = require "resty.redis" local str = require "resty.string" local cjson = require("cjson") local redis_host = "127.0.0.1" local redis_port = 6379 local function close_redis(red) if not red then return end local pool_max_idle_time = 10000 --毫秒 local pool_size = 100 --連接池大小 local ok, err = red:set_keepalive(pool_max_idle_time, pool_size) if not ok then ngx.say("set keepalive error : ", err) end end local function connect() local red = redis:new() red:set_timeout(1000) local ok, err = red:connect(redis_host, redis_port) if not ok then return false end --local res, err = red:auth("xiaoantimes") --if not res then -- ngx.say("failed to authenticate: ", err) -- return false --end --ok, err = red:select(1) --if not ok then -- return false --end return red end function has_token(token) local red = connect() if red == false then return false end local res, err = red:get(token) if not res then return false end close_redis(red) return true end function set_permissions(user_id,permissions) if (permissions==null) or( permissions==ngx.null) then return false end local str = cjson.encode(permissions) ngx.log(ngx.ERR,"set redis p:"..str) local red=connect() if red== false then return false end local ok, err = red:set(user_id,str) if not ok then return false end return true end function get_permissions(user_id) local red=connect() if red== false then return false end local res, err = red:get(user_id) if (not res) or (res == ngx.null) then return end ngx.log(ngx.ERR,"get redis p:"..res); local permissions=cjson.decode(res) return permissions end function get_user_id(token) local red = connect() local resp, err = red:get(token) if not resp then ngx.say("get msg error : ", err) return close_redis(red) end close_redis(red) return resp end
vim /usr/example/lua/test_token_tool.lua,加上以下的內容:
local tokentool= require "tokentool" local ret = tokentool.has_token("msg") ngx.log(ngx.ERR,ret) if ret == true then ngx.say("ok") else ngx.say("oops,error") end
在/usr/example/example.conf加上以下的內容:
location ~ /token_tool{ default_type 'text/html'; lua_code_cache on; content_by_lua_file /usr/example/lua/test_token_tool.lua; }
打開瀏覽器訪問http://116.196.177.123/token_tool,瀏覽器顯示:
ok
感謝你能夠認真閱讀完這篇文章,希望小編分享的“Openresty中RBAC、sql和redis模塊工具類的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。