目录
总结
背景
实操
安装 Casbin
创建一个 Casbin 模型
创建一个 Casbin 策略
加载 Casbin 模型和策略并创建一个路由
在本文中,我们将介绍如何结合 Casbin 对 HTTP 请求进行基于角色的访问控制 (RBAC) 鉴权,并支持请求路由参数。我们将使用 Go 语言中的 Casbin 库。
Casbin 是一个支持访问控制模型的库,可以轻松地集成到你的应用程序中。它支持多种访问控制模型,包括 RBAC、ABAC 等,可以与各种后端存储库(如文件、数据库等)集成,方便管理访问控制策略。
在本文中,我们将使用 Casbin 来实现基于 RBAC 的访问控制,为 HTTP 请求提供鉴权支持。
首先,我们需要安装 Casbin 库。你可以使用以下命令进行安装:
go get -u github.com/casbin/casbin
在 Casbin 中,模型用于定义访问策略,包括角色、资源和操作。下面是一个简单的 Casbin 模型示例:
[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
在上述 Casbin 模型中,我们定义了访问控制的请求、策略、角色和匹配器。具体来说,请求定义包括三个属性:请求主体 sub
、请求对象 obj
和请求操作 act
。策略定义和请求定义类似,包括三个属性:策略主体 sub
、策略对象 obj
和策略操作 act
。角色定义包括两个属性:角色名称 g
和角色成员 _
,其中 _
表示角色成员可以是任何字符串。我们使用 g
来定义角色之间的层级关系。匹配器定义了如何匹配请求和策略。
简单来说,就是请求的 sub
主体必须继承了策略的 sub
主体,我们使用 keyMatch2
函数来匹配请求对象和策略对象,而请求操作 act 则必须完全匹配。
keyMatch2
是 Casbin 中的一个匹配函数,用于在请求对象和策略对象中匹配带有通配符的字符串。
具体来说,keyMatch2
函数支持通配符 冒号 (:
) ,可以匹配任意长度的字符串。举个例子,假设我们有一个请求对象 /users/123
,策略对象为 /users/:id
,那么这两个对象就可以被 keyMatch2
函数匹配成功,因为 : 通配符可以匹配任意长度的字符串。
除了 keyMatch2
函数,Casbin 还支持其他的匹配函数,比如 keyMatch
、regexMatch
等。这些匹配函数可以帮助我们更加灵活地定义访问控制策略,以适应不同的业务场景。具体参考:
casbin——matchers中的函数
在 Casbin 中,策略用于定义实际的访问控制规则。你可以将策略存储在不同的后端(如数据库或文件)中。下面是一个简单的 Casbin 策略示例:
p, member, /depts, GET
p, member, /depts/:id, GET
p, admin, /depts, POST
p, admin, /depts/:id, PUT
p, admin, /depts/:id, DELETE
g, admin, member
g, zhangsan, admin
g, lisi, member
在上述的 Casbin 策略中,实际上我们定义了四个角色:admin
、member
、zhangsan
和 lisi
。
其中,admin
角色拥有对 /depts
路径下的所有请求操作的访问权限;member
角色仅拥有对 /depts
和 /depts/:id
路径下的 GET 请求操作的访问权限;zhangsan
角色继承了admin
角色的访问权限,因此也同样拥有对 /depts
路径下的所有请求操作的访问权限;lisi
角色仅拥有 member
角色的访问权限。
此外,我们使用冒号 (:
) 来表示路径参数,表示请求对象可以是一个具有参数的路径。这样,我们就可以更加灵活地定义访问控制策略,以适应不同的业务场景。
接下来,我们将创建一个名为 main.go
的 Go 文件,并添加以下代码:
package main
import (
"github.com/casbin/casbin"
"log"
"net/http"
)
func main() {
// 创建 Casbin 模型
e := casbin.NewEnforcer("model.conf", "policy.csv")
// 创建 HTTP 处理程序
http.HandleFunc("/depts/", func(w http.ResponseWriter, r *http.Request) {
// 获取当前用户、请求路径和请求方法
user := r.Header.Get("X-User")
path := r.URL.Path
method := r.Method
// 检查当前用户是否有权限访问该路径
if !e.Enforce(user, path, method) {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
// 如果有权限,则继续处理请求
// TODO: 处理请求
})
// 启动 HTTP 服务器
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
}
在上面的代码中,我们首先创建了一个 Casbin 模型,以及一个名为 /depts/
的 HTTP 处理程序。在处理程序中,我们获取了当前用户、请求路径和请求方法,并使用 Casbin 的 Enforce
方法来检查当前用户是否有权限访问该路径。如果没有权限,则返回 HTTP 状态码 403。
现在,我们可以使用以下命令运行该应用程序:
go run main.go
现在,我们已经成功实现了基于 RBAC 的访问控制,为 HTTP 请求提供了鉴权支持。但是,我们可能希望支持请求路由参数,以便更灵活地定义访问控制策略。