结合 Casbin 对 http 请求做 RBAC 鉴权以及添加请求路由参数支持

目录

总结

背景

实操

安装 Casbin

创建一个 Casbin 模型

创建一个 Casbin 策略

加载 Casbin 模型和策略并创建一个路由


总结

在本文中,我们将介绍如何结合 Casbin 对 HTTP 请求进行基于角色的访问控制 (RBAC) 鉴权,并支持请求路由参数。我们将使用 Go 语言中的 Casbin 库。

背景

Casbin 是一个支持访问控制模型的库,可以轻松地集成到你的应用程序中。它支持多种访问控制模型,包括 RBAC、ABAC 等,可以与各种后端存储库(如文件、数据库等)集成,方便管理访问控制策略。

在本文中,我们将使用 Casbin 来实现基于 RBAC 的访问控制,为 HTTP 请求提供鉴权支持。

实操

安装 Casbin

首先,我们需要安装 Casbin 库。你可以使用以下命令进行安装:

go get -u github.com/casbin/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 还支持其他的匹配函数,比如 keyMatchregexMatch 等。这些匹配函数可以帮助我们更加灵活地定义访问控制策略,以适应不同的业务场景。具体参考:

casbin——matchers中的函数

创建一个 Casbin 策略

在 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 策略中,实际上我们定义了四个角色:adminmemberzhangsanlisi

其中,admin 角色拥有对 /depts 路径下的所有请求操作的访问权限;member 角色仅拥有对 /depts/depts/:id 路径下的 GET 请求操作的访问权限;zhangsan 角色继承了admin 角色的访问权限,因此也同样拥有对 /depts 路径下的所有请求操作的访问权限;lisi 角色仅拥有 member 角色的访问权限。

此外,我们使用冒号 (:) 来表示路径参数,表示请求对象可以是一个具有参数的路径。这样,我们就可以更加灵活地定义访问控制策略,以适应不同的业务场景。

加载 Casbin 模型和策略并创建一个路由

接下来,我们将创建一个名为 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 请求提供了鉴权支持。但是,我们可能希望支持请求路由参数,以便更灵活地定义访问控制策略。

 
 

猜你喜欢

转载自blog.csdn.net/kingu_crimson/article/details/129816280