前言 RBAC
(Role-Based Access Control )基于角色的访问控制。
casbin
是一个强大的、高效的开源访问控制框架,其权限管理机制支持多种访问控制模型。
gorm-adapter
使用这个库,Casbin可以从Gorm加载政策支持的数据库或保存政策。
理解casbin的使用 具体可以看这篇文章:Basic Role-Based HTTP Authorization in Go with Casbin (中文翻译为在 Go 语言中使用 casbin 实现基于角色的 HTTP 权限控制 ),具体demo 我也加了详细注释。
这里有几个需要弄懂的:
模型文件的配置auth_model.conf
1 2 3 4 5 6 7 8 9 10 11 [request_definition] r = sub, obj, act [policy_definition] p = sub, obj, act [policy_effect] e = some(where (p.eft == allow)) [matchers] m = r.sub == p.sub && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*" )
Model CONF 至少应包含四个部分:[request_definition]
, [policy_definition]
, [policy_effect]
, [matchers]
如果 model 使用 RBAC, 还需要添加[role_definition]
部分。
sub, obj, act 表示经典三元组: 访问实体 (Subject),访问资源 (Object) 和访问方法 (Action)
更具体的可以直接看官方文档
策略文件policy.csv
1 2 3 4 p, admin, /*, * p, anonymous, /login, * p, member, /logout , * p, member, /member/*, *
admin 角色可以访问所有内容
member 角色可以访问以 /member/ 开头的路径和 logout 路径
未认证用户可以登陆
gorm-adapter 在上个个例子中,策略文件就是一个简单的 csv 文件,描述了哪些角色可以访问哪些路径等。但在实际项目中策略文件一般都会存储在数据库,这时候就用到了gorm-adapter
直接看官方给出的demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package main import ( "github.com/casbin/casbin/v2" gormadapter "github.com/casbin/gorm-adapter/v2" _ "github.com/go-sql-driver/mysql" ) func main () { //初始化一个Gorm adapter 并在Casbin enforcer中使用它: //Gorm adapter会使用一个名叫casbin的MySQL数据库 //如果不存在,将会自动创建 //或者通过 gormadapter.NewAdapterByDB(gormInstance)读取一个已经存在的数据库 a, _ := gormadapter.NewAdapter("mysql" , "mysql_username:mysql_password@tcp(127.0.0.1:3306)/" ) e, _ := casbin.NewEnforcer("examples/rbac_model.conf" , a) // Or you can use an existing DB "abc" like this: // The adapter will use the table named "casbin_rule" . // If it doesn't exist, the adapter will create it automatically. // a := gormadapter.NewAdapter("mysql", "mysql_username:mysql_password@tcp(127.0.0.1:3306)/abc", true) e.LoadPolicy()//从数据库加载策略 e.Enforce("alice", "data1", "read")// 检查许可 // 更改策略 // e.AddPolicy(...) // e.RemovePolicy(...) e.SavePolicy()//保存策略 }
实际项目举例 rbac_model.conf
模型文件配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 [request_definition] r = sub, obj, act [policy_definition] p = sub, obj, act [role_definition] g = _, _ [policy_effect] e = some(where (p.eft == allow)) [matchers] m = r.sub == p.sub && ParamsMatch(r.obj,p.obj) && r.act == p.act
qmplus.sql
表的定义并通过sql往数据库添加数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 /* Navicat Premium Data Transfer Source Server : qmplus Source Server Type : MySQL Source Server Version : 50644 Source Host : localhost:3306 Source Schema : qmplus Target Server Type : MySQL Target Server Version : 50644 File Encoding : 65001 Date: 15/04/2020 17:48:50 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for casbin_rule -- ---------------------------- DROP TABLE IF EXISTS `casbin_rule`; CREATE TABLE `casbin_rule` ( `p_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `v0` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `v1` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `v2` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `v3` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `v4` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `v5` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of casbin_rule -- ---------------------------- INSERT INTO `casbin_rule` VALUES ('p' , '8881' , '/base/login' , 'POST' , '' , '' , '' ); ...
更新Casbin规则
1 2 3 4 5 6 7 8 func UpdateCasbinApi(oldPath string, newPath string, oldMethod string, newMethod string) error { var cs []model.CasbinModel err := global.GVA_DB.Table("casbin_rule" ).Where("v1 = ? AND v2 = ?" , oldPath, oldMethod).Find(&cs).Updates(map[string]string{ "v1" : newPath, "v2" : newMethod, }).Error return err }
其中GVA_DB
就是全局定义的gorm.DB实例
1 2 3 4 var ( GVA_DB *gorm.DB ... )
资料
RBAC用户、角色、权限、组设计方案 casbin 基于角色的访问控制