詳情 能夠查看 我寫的這個項目 https://github.com/hequan2017/go-admingit
利用的庫: github.com/casbin/casbin github.com/gin-gonic/gin github.com/facebookgo/inject casbin文檔: https://casbin.org/zh-CN/ 下面例子 未利用 casbin 的 adapter, 而是啓動的時候 先初始化, 而後經過數據庫裏面的 對應關係 ,動態加載全部的 權限條目 而後經過中間件去判斷,若是有更新,能夠動態修改更新 權限條目.
rbac_model.conf [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) == true \ && keyMatch2(r.obj, p.obj) == true \ && regexMatch(r.act, p.act) == true
b_auth.go package bll //gin-allin/models 爲本身的項目 請忽略 import ( "gin-allin/models" "github.com/casbin/casbin" ) //models.Auth 爲 User表 實際能夠寫成本身的USER 表 type Role struct { Role *models.Auth `inject:""` Enforcer *casbin.Enforcer `inject:""` } // LoadPolicy 加載角色權限策略, func (a *Role) LoadPolicy(roleID string) error { a.Enforcer.AddPolicy(roleID, "/api/v1/auth_info","GET") return nil }
b_common.go package bll //把 權限表 注入到 Common type Common struct { Role *Role `inject:""` } inject.go
package inject import ( "gin-allin/bll" "github.com/casbin/casbin" "github.com/facebookgo/inject" "os" ) // Object 注入對象 type Object struct { Common *bll.Common Enforcer *casbin.Enforcer } // Init 初始化依賴注入 func Init() *Object { g := new(inject.Graph) // 注入casbin dir, _ := os.Getwd() path := dir + "\\src\\gin-allin\\conf\\rbac_model.conf" enforcer := casbin.NewEnforcer(path, false) _ = g.Provide(&inject.Object{Value: enforcer}) // 注入Common 也就是 Role Common := new(bll.Common) _ = g.Provide(&inject.Object{Value: Common}) if err := g.Populate(); err != nil { panic("初始化依賴注入發生錯誤:" + err.Error()) } // 返回 注入完的對象 return &Object{ Enforcer: enforcer, Common :Common, } }
casb.go package casb import ( "gin-allin/inject" "github.com/gin-gonic/gin" "net/http" ) // 權限判斷 func CasbinMiddleware(obj *inject.Object) gin.HandlerFunc { return func(c *gin.Context) { // 判斷 權限 是否爲 true if b, err := obj.Enforcer.EnforceSafe("hequan", c.Request.URL.Path, c.Request.Method); err != nil { c.JSON(http.StatusUnauthorized, gin.H{ "code": "權限 判斷錯誤", "msg": "權限 判斷錯誤", "data": "權限 判斷錯誤", }) c.Abort() return } else if !b { c.JSON(http.StatusUnauthorized, gin.H{ "code": "沒有權限", "msg": "沒有權限", "data": "沒有權限", }) c.Abort() return } c.Next() } }
router.go package routers func InitRouter() *gin.Engine { // 生成對象 obj := inject.Init() err := loadCasbinPolicyData(obj) if err != nil { panic("加載casbin策略數據發生錯誤:" + err.Error()) } apiv1.Use(casb.CasbinMiddleware(obj)) } // 加載casbin策略數據 加載 hequan 的一個權限 func loadCasbinPolicyData(obj *inject.Object) error { err := obj.Common.Role.LoadPolicy("hequan") if err != nil { fmt.Println(err) return err } return nil }
當 用戶 hequan 去 訪問 /api/v1/auth_info 時,會去判斷是否有GET 權限,有就經過,沒有就拒絕。 測試 能夠把 用戶名 寫成其餘的, 再從新啓動,此時,中間件判斷 不經過,就會返回 拒絕。