网站建设相关资料,许昌城乡建设局网站,网站建设需求书,wordpress 导出 word文章目录 0. 背景1. 准备工作2. 权限配置以及增删改查2.1 策略和组使用规范2.2 用户以及组关系的增删改查2.2.1 获取所有用户以及关联的角色2.2.2 角色组中添加用户2.2.3 角色组中删除用户 2.3 角色组权限的增删改查2.3.1 获取所有角色组权限2.3.2 创建角色组权限2.3.3 修改角色… 文章目录 0. 背景1. 准备工作2. 权限配置以及增删改查2.1 策略和组使用规范2.2 用户以及组关系的增删改查2.2.1 获取所有用户以及关联的角色2.2.2 角色组中添加用户2.2.3 角色组中删除用户 2.3 角色组权限的增删改查2.3.1 获取所有角色组权限2.3.2 创建角色组权限2.3.3 修改角色组权限2.3.4 删除角色组权限2.3.5 验证用户权限 3. 测试以及完整代码3.1 casbin_service.go3.2 casbin_service_test.go3.3测试结果 4. 结语 0. 背景 Casbin是用于Golang项目的功能强大且高效的开源访问控制库。 强大通用也意味着概念和配置较多具体到实际应用(以Gin Web框架开发需要解决以下问题 权限配置的存储以及增删改查Gin框架的中间件如何实现 经过一番摸索实践出经验计划分为三个章节循序渐进的介绍使用方法 Casbin概念介绍以及库使用使用Gorm存储Casbin权限配置以及增删改查实现Gin鉴权中间件 1. 准备工作 接上一章略改进一下将model.conf文件内容存储到go字符串中,最终代码如下: package mainimport (loggithub.com/casbin/casbin/v2github.com/casbin/casbin/v2/modelgormadapter github.com/casbin/gorm-adapter/v3github.com/glebarez/sqlitegorm.io/gorm
)func main() {db, err : gorm.Open(sqlite.Open(test.db), gorm.Config{})if err ! nil {panic(failed to connect database)}a, err : gormadapter.NewAdapterByDB(db)if err ! nil {panic(new gorm adapter error: err.Error())}m, err : model.NewModelFromString([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 g(r.sub, p.sub) keyMatch2(r.obj,p.obj) r.act p.act)if err ! nil {panic(new model error: err.Error())}e, err : casbin.NewEnforcer(m, a)if err ! nil {panic(new casbin enforcer error: err.Error())}e.LoadPolicy()// 添加策略ok, err : e.AddPolicy(admin, /api/user, GET)log.Println(add admin /api/user GET: , ok, err)ok, err e.AddGroupingPolicy(leo, admin)log.Println(add leo to admin group: , ok, err)e.SavePolicy()ok, err e.Enforce(leo, /api/user, GET)log.Println(leo GET /api/user :, ok, err)ok, err e.Enforce(leo, /api/user, DELETE)log.Println(leo DELETE /api/user :, ok, err)
} 上述代码默认使用的gormadapter.CasbinRule对应的Go结构和数据库表如下 type CasbinRule struct {ID uint gorm:primaryKey;autoIncrementPtype string gorm:size:100V0 string gorm:size:100V1 string gorm:size:100V2 string gorm:size:100V3 string gorm:size:100V4 string gorm:size:100V5 string gorm:size:100
}2. 权限配置以及增删改查 以上准备知识仅了解和casbin基本操作以及如何配合gorm存储到DB中还需要完善权限以及提供增删改查操作 2.1 策略和组使用规范 casbin的policy十分灵活具体到自己业务使用中我这里按以下两条规则使用基本能满足业务需求 所有策略只针对角色组设置用户关联到组(一个用户可以有多个组) 如下两个角色组admin和user组admin组能查询和删除用户user组只能查询用户 ptypev0v1v2v3v4v5padmin/api/userGETpadmin/api/userDELETEpuser/api/userGET………gleoadmingleo2user 基础代码如下下一节给CasbinService添加增删改查功能 package mainimport (github.com/casbin/casbin/v2github.com/casbin/casbin/v2/modelgormadapter github.com/casbin/gorm-adapter/v3gorm.io/gorm
)type CasbinService struct {enforcer *casbin.Enforceradapter *gormadapter.Adapter
}func NewCasbinService(db *gorm.DB) (*CasbinService, error) {a, err : gormadapter.NewAdapterByDB(db)if err ! nil {return nil, err}m, err : model.NewModelFromString([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 g(r.sub, p.sub) keyMatch2(r.obj,p.obj) r.act p.act)if err ! nil {return nil, err}e, err : casbin.NewEnforcer(m, a)if err ! nil {return nil, err}return CasbinService{adapter: a, enforcer: e}, nil
}2.2 用户以及组关系的增删改查
2.2.1 获取所有用户以及关联的角色 根据2.1中示范数据预期输出 [{username: leo,roleNames: [admin]
}, {username: leo2,roleNames: [user]
}]获取所有用户以及关联的角色代码片段 type User struct {UserName stringRoleNames []string
}// 获取所有用户以及关联的角色
func (c *CasbinService) GetUsers() (users []User) {p : c.enforcer.GetGroupingPolicy()usernameUser : make(map[string]*User, 0)for _, _p : range p {username, usergroup : _p[0], _p[1]if v, ok : usernameUser[username]; ok {usernameUser[username].RoleNames append(v.RoleNames, usergroup)} else {usernameUser[username] User{UserName: username, RoleNames: []string{usergroup}}}}for _, v : range usernameUser {users append(users, *v)}return
}
2.2.2 角色组中添加用户
// 角色组中添加用户, 没有组默认创建
func (c *CasbinService) UpdateUserRole(username, rolename string) error {_, err : c.enforcer.AddGroupingPolicy(username, rolename)return err
}2.2.3 角色组中删除用户
// 角色组中删除用户
func (c *CasbinService) DeleteUserRole(username, rolename string) error {_, err : c.enforcer.RemoveGroupingPolicy(username, rolename)return err
}2.3 角色组权限的增删改查
2.3.1 获取所有角色组权限 根据2.1中示范数据预期输出形式 [{roleName: admin,url: /api/user,method: DELETE
}, {roleName: admin,url: /api/user,method: GET
}, {roleName: user,url: /api/user,method: GET
}]获取所有角色组权限 go
// (RoleName, Url, Method) 对应于 CasbinRule 表中的 (v0, v1, v2)
type RolePolicy struct {RoleName string gorm:column:v0Url string gorm:column:v1Method string gorm:column:v2
}// 获取所有角色组权限
func (c *CasbinService) GetRolePolicy() (roles []RolePolicy, err error) {err c.adapter.GetDb().Model(gormadapter.CasbinRule{}).Where(ptype p).Find(roles).Errorif err ! nil {return nil, err}return
}
2.3.2 创建角色组权限
// 创建角色组权限, 已有的会忽略
func (c *CasbinService) CreateRolePolicy(r RolePolicy) error {// 不直接操作数据库利用enforcer简化操作err : c.enforcer.LoadPolicy()if err ! nil {return err}_, err c.enforcer.AddPolicy(r.RoleName, r.Url, r.Method)if err ! nil {return err}return c.enforcer.SavePolicy()
}
2.3.3 修改角色组权限
// 修改角色组权限
func (c *CasbinService) UpdateRolePolicy(old, new RolePolicy) error {_, err : c.enforcer.UpdatePolicy([]string{old.RoleName, old.Url, old.Method},[]string{new.RoleName, new.Url, new.Method})if err ! nil {return err}return c.enforcer.SavePolicy()
}2.3.4 删除角色组权限
// 删除角色组权限
func (c *CasbinService) DeleteRolePolicy(r RolePolicy) error {_, err : c.enforcer.RemovePolicy(r.RoleName, r.Url, r.Method)if err ! nil {return err}return c.enforcer.SavePolicy()
}2.3.5 验证用户权限
// 验证用户权限
func (c *CasbinService) CanAccess(username, url, method string) (ok bool, err error) {return c.enforcer.Enforce(username, url, method)
}3. 测试以及完整代码
3.1 casbin_service.go
package mainimport (github.com/casbin/casbin/v2github.com/casbin/casbin/v2/modelgormadapter github.com/casbin/gorm-adapter/v3gorm.io/gorm
)/*
按如下约定:1. 所有策略只针对角色组设置2. 用户关联到组(一个用户可以有多个组)
---------------------------------------------
| ptype | v0 | v1 | v2 | v3 | v4 | v5 |
---------------------------------------------
| p | admin | /api/user | GET | | | |
---------------------------------------------
| p | admin | /api/user | DELETE | | | |
---------------------------------------------
| p | user | /api/user | GET | | | |
---------------------------------------------
| ... | ... | ... | | | | |
---------------------------------------------
| g | leo | admin | | | | |
---------------------------------------------
| g | leo2 | admin | | | | |
---------------------------------------------
| g | leo3 | user | | | | |
---------------------------------------------
*/
type CasbinService struct {enforcer *casbin.Enforceradapter *gormadapter.Adapter
}func NewCasbinService(db *gorm.DB) (*CasbinService, error) {a, err : gormadapter.NewAdapterByDB(db)if err ! nil {return nil, err}m, err : model.NewModelFromString([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 g(r.sub, p.sub) keyMatch2(r.obj,p.obj) r.act p.act)if err ! nil {return nil, err}e, err : casbin.NewEnforcer(m, a)if err ! nil {return nil, err}return CasbinService{adapter: a, enforcer: e}, nil
}// (RoleName, Url, Method) 对应于 CasbinRule 表中的 (v0, v1, v2)
type RolePolicy struct {RoleName string gorm:column:v0Url string gorm:column:v1Method string gorm:column:v2
}// 获取所有角色组权限
func (c *CasbinService) GetRolePolicy() (roles []RolePolicy, err error) {err c.adapter.GetDb().Model(gormadapter.CasbinRule{}).Where(ptype p).Find(roles).Errorif err ! nil {return nil, err}return
}// 创建角色组权限, 已有的会忽略
func (c *CasbinService) CreateRolePolicy(r RolePolicy) error {// 不直接操作数据库利用enforcer简化操作err : c.enforcer.LoadPolicy()if err ! nil {return err}_, err c.enforcer.AddPolicy(r.RoleName, r.Url, r.Method)if err ! nil {return err}return c.enforcer.SavePolicy()
}// 修改角色组权限
func (c *CasbinService) UpdateRolePolicy(old, new RolePolicy) error {_, err : c.enforcer.UpdatePolicy([]string{old.RoleName, old.Url, old.Method},[]string{new.RoleName, new.Url, new.Method})if err ! nil {return err}return c.enforcer.SavePolicy()
}// 删除角色组权限
func (c *CasbinService) DeleteRolePolicy(r RolePolicy) error {_, err : c.enforcer.RemovePolicy(r.RoleName, r.Url, r.Method)if err ! nil {return err}return c.enforcer.SavePolicy()
}type User struct {UserName stringRoleNames []string
}// 获取所有用户以及关联的角色
func (c *CasbinService) GetUsers() (users []User) {p : c.enforcer.GetGroupingPolicy()usernameUser : make(map[string]*User, 0)for _, _p : range p {username, usergroup : _p[0], _p[1]if v, ok : usernameUser[username]; ok {usernameUser[username].RoleNames append(v.RoleNames, usergroup)} else {usernameUser[username] User{UserName: username, RoleNames: []string{usergroup}}}}for _, v : range usernameUser {users append(users, *v)}return
}// 角色组中添加用户, 没有组默认创建
func (c *CasbinService) UpdateUserRole(username, rolename string) error {_, err : c.enforcer.AddGroupingPolicy(username, rolename)return err
}// 角色组中删除用户
func (c *CasbinService) DeleteUserRole(username, rolename string) error {_, err : c.enforcer.RemoveGroupingPolicy(username, rolename)return err
}// 验证用户权限
func (c *CasbinService) CanAccess(username, url, method string) (ok bool, err error) {return c.enforcer.Enforce(username, url, method)
}
3.2 casbin_service_test.go
package mainimport (testinggithub.com/glebarez/sqlitegorm.io/gorm
)func TestCasbinService(t *testing.T) {db, err : gorm.Open(sqlite.Open(test.db), gorm.Config{})if err ! nil {panic(failed to connect database)}s, err : NewCasbinService(db)if err ! nil {t.Fatalf(new service error: %v, err)}// 创建个用户分别关联到admin和user组, leo2既是admin组又是user组t.Logf(create user: leo with group: admin result: %v, s.UpdateUserRole(leo, admin))t.Logf(create user: leo with group: admin result: %v, s.UpdateUserRole(leo2, admin))t.Logf(create user: leo with group: admin result: %v, s.UpdateUserRole(leo2, user))t.Log()t.Logf(users is: %v\n, s.GetUsers())// 针对admin和user组创建三条策略t.Log(create admin /api/user GET: , s.CreateRolePolicy(RolePolicy{RoleName: admin, Url: /api/user, Method: GET}))t.Log(create admin /api/user DELETE: , s.CreateRolePolicy(RolePolicy{RoleName: admin, Url: /api/user, Method: DELETE}))t.Log(create user /api/user GET: , s.CreateRolePolicy(RolePolicy{RoleName: user, Url: /api/user, Method: GET}))t.Log(all policy is: )t.Log(s.GetRolePolicy())t.Log(delete admin /api/user GET, s.DeleteRolePolicy(RolePolicy{RoleName: admin, Url: /api/user, Method: GET}))
}
3.3测试结果 4. 结语 基本的权限模型设计以及操作函数均已设计正常 下一章开始结合gin框架设计一个中间件 实现casbin权限验证