Most applications eventually run into authorization and permission management. Sometimes you want something you can plug into a small personal project without much setup, but that can also scale to more complicated rules in a larger system. Casbin fits that role well. It supports multiple programming languages, and in Python, PyCasbin is straightforward enough to get running with only a few files.
What Casbin is
Casbin is an open-source access control library built to enforce authorization rules efficiently. Its main strength is that it supports multiple access control models, so it is not limited to a single way of describing permissions.
Installing PyCasbin
First install the Python package:
pip install casbin
Besides the library itself, a basic setup also needs two configuration files: model.conf and policy.csv.
model.confdefines the access control model.policy.csvstores the actual permission rules for users.
A minimal Python script can load both files like this:
import casbin
import os
# model.conf 和 policy.csv 文件地址
model_dir = os.path.join(os.path.dirname(__file__), 'model.conf')
policy_dir = os.path.join(os.path.dirname(__file__), 'policy.csv')
# 加载配置文件
e = casbin.Enforcer(model_dir,policy_dir)
A simple ACL model
In this example, model.conf contains an ACL-style configuration:
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
This model is very direct:
subis the subject, usually the userobjis the object or resource being accessedactis the action performed on that resource
The matching rule requires all three values to line up exactly with a policy entry.
Defining permissions with policy.csv
The policy file can contain rules such as:
p, alice, data1, read
p, bob, data2, write
That means:
alicecanreaddata1bobcanwritedata2
Testing permissions in Python
Once the model and policy are in place, permission checks are just a call to the enforcer. The full example script looks like this:
import casbin
import os
# model.conf 和 policy.csv 文件地址
model_dir = os.path.join(os.path.dirname(__file__), 'model.conf')
policy_dir = os.path.join(os.path.dirname(__file__), 'policy.csv')
# 加载配置文件
e = casbin.Enforcer(model_dir,policy_dir)
sub = "alice" # 想要访问资源的用户
obj = "data1" # 将要被访问的资源
act = "read" # 用户对资源进行的操作
def getEnforce(sub, obj, act):
"""
执行器的封装
"""
if e.enforce(sub, obj, act):
# 允许alice读取data1
return True
else:
# 拒绝请求,抛出异常
return False
if __name__ == '__main__':
print(getEnforce(sub,obj,act))
Running this script prints True, because the policy allows alice to read data1. The example is simple enough that the comments already explain most of what is happening: load the model, load the policy, then ask the enforcer whether a request should be allowed.
Storing policies in a database
Keeping policies in a flat file is useful for a quick start, but real applications often need something closer to production usage. A database-backed policy store is usually more practical.
For that, you can use casbin_sqlalchemy_adapter, which wraps a lot of the database-related Casbin operations so you do not have to build them yourself.
Install it with:
pip install casbin_sqlalchemy_adapter
After that, replace the policy.csv path with a database adapter. The first part of test.py becomes:
# model.conf 和 policy.csv 文件地址
model_dir = os.path.join(os.path.dirname(__file__), 'model.conf')
# policy_dir = os.path.join(os.path.dirname(__file__), 'policy.csv')
# 组装数据库的绝对地址
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DB_DIR = os.path.join(BASE_DIR, 'test.db')
# 数据库访问地址
SQLALCHEMY_DATABASE_URL = "sqlite:///" + DB_DIR
# 从数据库加载casbin的policy
adapter = casbin_sqlalchemy_adapter.Adapter(SQLALCHEMY_DATABASE_URL)
e = casbin.Enforcer(model_dir, adapter)
e.add_policy(["alice", "data1", "read"])
Here the file-based policy path is commented out and replaced with a database connection. When the program runs, it creates a database and a table named casbin_rule. The contents of that table correspond to the same kind of rules you would otherwise place in policy.csv.
Policies can be added with e.add_policy(), and the adapter also supports the usual management operations such as adding multiple rules, updating them, or deleting them.
Once this change is made, the permission check behaves the same way as it did with the CSV file, but the policies are now stored in a database instead. That makes the setup much more practical for actual applications.
Casbin is not limited to this ACL example either. It can support other permission models such as RBAC. Even from a small example like this, it is easy to see why it is a handy framework: the setup is uncomplicated, the behavior is clear, and it removes a lot of repetitive authorization work.