阿拉平平
读完需要
分钟
速读仅需 4 分钟
前段时间试了下用 Gin 编写接口,但是在权限控制这块,网上很多资料都是用 casbin 来实现。网上关于 casbin 的文档良莠不齐,有的甚至看得我一脸懵逼。之后在 V 站上看到有大佬推荐了 Ladon,于是我抽空折腾了下。
文中我将使用 Gin 和 Ladon 实现一个简易的 ACL 接口,通过向接口发送数据判断某用户是否具有操作资源的权限。
1. 简介
2. 接口
$ cd Ladon-demo
$ go get -u github.com/gin-gonic/gin
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run() // listen and serve on 0.0.0.0:8080
}
$ go run main.go
$ curl -s http://127.0.0.1:8080/ping
{"message":"pong"}
3. 概念
因此,向接口发送的数据需要包含:
subject:对应「谁」,即主体。
action:对应「可以做」,即操作的种类,比如增删改查。
resource:对应「做什么」,即具体操作的资源。
context:对应「特定环境」,即一些限制条件,可选。
转换成 JSON 格式,大致如下:
{
"subject": "users:peter",
"action" : "delete",
"resource": "resources:articles:ladon-introduction",
"context": {
"remoteIP": "192.168.0.5"
}
}
{
"description": "One policy to rule them all.",
"subjects": ["users:<peter|ken>", "users:maria", "groups:admins"],
"actions" : ["delete", "<create|update>"],
"effect": "allow",
"resources": [
"resources:articles:<.*>",
"resources:printer"
],
"conditions": {
"remoteIP": {
"type": "CIDRCondition",
"options": {
"cidr": "192.168.0.1/16"
}
}
}
}
4. 实例
老板张三开了家理发店,并且雇佣了理发界三巨头 Tony、Kevin 和 Allen。现在需要为三位老师开通理发业务的权限。
4.1 安装导入
安装前确保 Go 版本在 1.11 以上。
$ go get github.com/ory/ladon
import "github.com/ory/ladon"
4.2 创建策略
var pol = &ladon.DefaultPolicy{
ID: "0",
Description: "Hair Design",
Subjects: []string{"<Tony|Kevin|Allen>"},
Resources: []string{
"resources:hair",
},
Actions: []string{"delete", "<create|update>"},
Effect: ladon.AllowAccess,
}
说明:
ID:策略的标识。
Description:策略的描述。
Subjects:策略的主体。<> 内为正则表达式。
Resources:策略的资源。
Actions:策略的操作类型。
Effect:AllowAccess 表示允许。DenyAccess 表示拒绝。
4.3 添加接口
现在添加一个接口 /check,通过 POST 请求发送数据来验证刚刚创建的策略。
修改 main.go,加入以下代码:
r.POST("/check", func(c *gin.Context) {
// 声明数据结构体
accessRequest := &ladon.Request{}
var message string
// 绑定接口发送的数据
if err := c.BindJSON(accessRequest); err != nil {
fmt.Println(err)
} else {
// 实例化 warden
warden := &ladon.Ladon{
// 数据持久化
Manager: memory.NewMemoryManager(),
// 打印审计日志
AuditLogger: &ladon.AuditLoggerInfo{},
}
// 添加策略
warden.Manager.Create(pol)
// 判断是否拥有权限
if err := warden.IsAllowed(accessRequest); err != nil {
message = "无操作权限"
} else {
message = "有操作权限"
}
c.JSON(200, gin.H{
"message": message,
})
}
})
需要注意的是,在实例化 warden 时指定了用内存方式做数据持久化,因此需要导入 memory:
import "github.com/ory/ladon/manager/memory"
4.4 测试接口
先查看下 Tony 老师有没有权限:
$ curl -s
> -X POST
> -H "Content-Type: application/json"
> -d@-
> "http://127.0.0.1:8080/check" <<EOF
> {
> "subject": "Tony",
> "action" : "delete",
> "resource": "resources:hair"
> }
> EOF
{"message":"有操作权限"}
$ curl -s
> -X POST
> -H "Content-Type: application/json"
> -d@-
> "http://127.0.0.1:8080/check" <<EOF
> {
> "subject": "张三",
> "action" : "delete",
> "resource": "resources:hair"
> }
> EOF
{"message":"无操作权限"}
可以看到,测试结果符合我们的预期。张老板很开心,但是又提了个需求。
4.5 限定条件
张老板提出:现在叫 Tony 的人实在太多了,不能是个 Tony 就给他理发业务的权限。
张老板的需求不无道理,所以我们完善下之前的代码,给发送的数据加个限定条件,比如数据中需要指明 boss。
在 pol 里加入 Conditions:
var pol = &ladon.DefaultPolicy{
...
Conditions: ladon.Conditions{
"boss": &ladon.StringEqualCondition{
Equals: "张三",
},
},
}
这里的 StringEqualCondition 用于判断字符串是否相等,即判断 boss 是否等于 张三。当然,Ladon 还自带了其它限定条件,同时也支持自定义,这里就不展开了。
接下来测试下接口:
$ curl -s
> -X POST
> -H "Content-Type: application/json"
> -d@-
> "http://127.0.0.1:8080/check" <<EOF
> {
> "subject": "Tony",
> "action" : "delete",
> "resource": "resources:hair"
> }
> EOF
{"message":"无操作权限"}
这里没有指定 boss,所以 Tony 老师就没有权限了。现在指定下 boss 再测试下:
$ curl -s
> -X POST
> -H "Content-Type: application/json"
> -d@-
> "http://127.0.0.1:8080/check" <<EOF
> {
> "subject": "Tony",
> "action" : "delete",
> "resource": "resources:hair",
> "context": {
> "boss": "张三"
> }
> }
> EOF
{"message":"有操作权限"}
可以看到,在指定 boss 后,Tony 老师又获得了权限。
5. 结语
有一说一,Ladon 相关的文档的确不多,功能也不如 casbin 强大。但是如果你熟悉 AWS IAM 策略的话,相信很快就能上手,在权限控制上也可以多一种选择。
References
[1]
Ladon: https://github.com/ory/ladon
原文始发于微信公众号(阿拉平平):Ladon 折腾手记:结合 Gin 开发一个简易 ACL 接口
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/287964.html