最近的项目需要设计一个比较复杂的权限系统,用到了casbin,简单做个使用说明。
1. 设计理念
casbin是一套权限控制框架,支持多种经典的访问控制模型(ACL、RBAC等)。casbin通过PERM (Policy, Effect, Request, Matcher) 四类配置,即可组合出各种复杂权限模型。
- Policy: 定义权限的规则
- Effect: 定义当命中多个 Policy 之后的结果, allow or deny
- Request: 定义访问请求,
- Matcher: 判断 Request 是否满足 Policy
2. RBAC demo
通过官网上的一个RBAC的例子来理解上述内容。一般有两个文件来定义model.conf和rbac_policy.csv。
首先在model.conf文件中定义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) && r.obj == p.obj && r.act == p.act
- [request_definition]定义Request格式:sub(用户或角色),obj(某个资源,比如url),act(访问的动作,比如GET)
- [policy_definition]定义Policy的格式规则,也是sub,obj,act,即插入的policy规则需要满足sub,obj,act的要求
- [role_definition]定义Group,当使用RBAC时,用户所属的角色可以通过此来定义,常见有两种:
- g = , 表示用户、角色
- g = ,,_ 表示用户、角色、域
- [policy_effect]定义Policy生效规则,e = some(where (p.eft == allow)表示任意一条policy rule命中即生效;
- [matchers]定义匹配request 和 policy 的方式。
其次是rbac_policy.csv,具体保存Policy和group规则。
p, alice, data1, read
p, bob, data2, write
p, data2_admin, data2, read
p, data2_admin, data2, write
g, alice, data2_admin
官网这个例子很简单,
- p, alice, data1, read表示添加的是一条Policy,Alice用户可以read data1
- p, data2_admin, data2, read表示角色data2_admin可以read data2
- g, alice, data2_admin表示alice的角色为data2_admin
以上都是配置文件,完成配置后,具体使用时
import casbin
e = casbin.Enforcer("path/to/model.conf", "path/to/policy.csv")
sub = "alice" # the user that wants to access a resource.
obj = "data1" # the resource that is going to be accessed.
act = "read" # the operation that the user performs on the resource.
if e.enforce(sub, obj, act):
# permit alice to read data1
pass
else:
# deny the request, show an error
pass
3. RBAC in Web
官网这个例子比较基本,再举一个更常见的例子,如何casbin应用在Web server中。可以将路由route作为obj,请求方式Method作为act,登录用户的角色作为sub,在每一次请求时,把这3个参数传递给e.Enforce,即可判断。
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) && r.obj == p.obj && r.act == p.act
policy.csv:
p, admin, /hello, GET
g, guoxingyu, admin
app.py:
import casbin
from flask import Flask, request, abort
app = Flask(__name__)
e = casbin.Enforcer("./conf/model.conf", "./conf/policy.csv")
@app.route('/hello', methods=['GET'])
def hello():
return '<h1>hello world</h1>'
@app.before_request
def check_request():
name = request.args.get('username')
url = request.path
act = request.method
if not e.enforce(name, url, act):
return abort(401)
@app.errorhandler(401)
def error(arg):
return "用户没权限"
效果:
当参数username是guoxingyu时,请求成功
1585492507941.jpg
当参数username是other时,请求失败
1585492538950.jpg
网友评论