本文目录导读:

在Python中分配用户权限,通常有几种常见的实现方案,取决于你的应用场景,我为你整理了从简单到复杂的几种典型案例:
基于角色的权限控制(RBAC) - 最常用
这是最常见的权限管理方式,适用于Web应用、后台管理系统等。
简单实现示例:
from enum import Enum
from functools import wraps
# 定义权限类型
class Permission(Enum):
CREATE_USER = "create_user"
DELETE_USER = "delete_user"
VIEW_REPORT = "view_report"
EDIT_SETTINGS = "edit_settings"
# 定义角色及其权限
ROLES = {
"admin": [Permission.CREATE_USER, Permission.DELETE_USER,
Permission.VIEW_REPORT, Permission.EDIT_SETTINGS],
"editor": [Permission.CREATE_USER, Permission.VIEW_REPORT],
"viewer": [Permission.VIEW_REPORT]
}
class User:
def __init__(self, username, role):
self.username = username
self.role = role
self.permissions = ROLES.get(role, [])
def has_permission(self, permission):
return permission in self.permissions
# 权限装饰器
def require_permission(permission):
def decorator(func):
@wraps(func)
def wrapper(user, *args, **kwargs):
if not user.has_permission(permission):
raise PermissionError(f"用户{user.username}没有权限执行此操作")
return func(user, *args, **kwargs)
return wrapper
return decorator
# 使用示例
@require_permission(Permission.DELETE_USER)
def delete_user(admin, target_user_id):
print(f"用户{admin.username}删除了用户{target_user_id}")
# 测试
admin = User("张三", "admin")
editor = User("李四", "editor")
try:
delete_user(admin, 1) # 成功
delete_user(editor, 2) # 抛出权限错误
except PermissionError as e:
print(f"错误: {e}")
基于位运算的权限控制 - 高性能
适合需要高性能、且权限数量不超过64个的场景(如游戏、高性能服务)。
class Permission:
# 使用2的幂定义权限
READ = 1 << 0 # 1
WRITE = 1 << 1 # 2
DELETE = 1 << 2 # 4
ADMIN = 1 << 3 # 8
class UserPermissions:
def __init__(self, permissions=0):
self.permissions = permissions
def add_permission(self, perm):
self.permissions |= perm
def remove_permission(self, perm):
self.permissions &= ~perm
def has_permission(self, perm):
return (self.permissions & perm) == perm
def has_any_permission(self, *perms):
for perm in perms:
if self.has_permission(perm):
return True
return False
# 使用示例
user_perms = UserPermissions()
user_perms.add_permission(Permission.READ | Permission.WRITE)
print(f"是否有读权限: {user_perms.has_permission(Permission.READ)}") # True
print(f"是否有删除权限: {user_perms.has_permission(Permission.DELETE)}") # False
print(f"是否有读写权限: {user_perms.has_permission(Permission.READ | Permission.WRITE)}") # True
# 权限组合直接存储到数据库 (仅需一个整数字段)
db_storage = user_perms.permissions # 存储为整数: 3
使用第三方库 - Django的权限系统
如果你在使用Django框架,推荐使用其内置权限系统:
# Django 模型示例
from django.contrib.auth.models import User, Permission
from django.contrib.contenttypes.models import ContentType
from django.db import models
class Article(models.Model):= models.CharField(max_length=100)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
permissions = [
("publish_article", "可以发布文章"),
("archive_article", "可以归档文章"),
]
# 分配权限
def assign_permissions(user):
# 获取特定权限
content_type = ContentType.objects.get_for_model(Article)
permission = Permission.objects.get(
codename='publish_article',
content_type=content_type,
)
# 为用户分配权限
user.user_permissions.add(permission)
# 或者使用组分配
from django.contrib.auth.models import Group
editor_group = Group.objects.get(name='编辑')
editor_group.permissions.add(permission)
user.groups.add(editor_group)
# 检查权限
def check_permission(user):
if user.has_perm('myapp.publish_article'):
# 有权限
pass
# 在模板中使用
# {% if perms.myapp.publish_article %}
# 有权限
# {% endif %}
ACL(访问控制列表) - 细粒度控制
适合需要精确控制每个用户对每个资源的访问:
from dataclasses import dataclass
from typing import Dict, Set
@dataclass
class Resource:
id: str
type: str
class AccessControlList:
def __init__(self):
# 格式: {用户ID: {资源ID: {权限集合}}}
self.acl: Dict[str, Dict[str, Set[str]]] = {}
def grant_permission(self, user_id: str, resource: Resource, permission: str):
if user_id not in self.acl:
self.acl[user_id] = {}
if resource.id not in self.acl[user_id]:
self.acl[user_id][resource.id] = set()
self.acl[user_id][resource.id].add(permission)
def revoke_permission(self, user_id: str, resource: Resource, permission: str):
if user_id in self.acl and resource.id in self.acl[user_id]:
self.acl[user_id][resource.id].discard(permission)
def check_permission(self, user_id: str, resource: Resource, permission: str) -> bool:
if user_id in self.acl:
user_perms = self.acl[user_id]
if resource.id in user_perms:
return permission in user_perms[resource.id]
return False
# 使用示例
acl = AccessControlList()
doc = Resource("doc-001", "document")
# 授予权限
acl.grant_permission("user1", doc, "read")
acl.grant_permission("user1", doc, "write")
# 检查权限
print(acl.check_permission("user1", doc, "read")) # True
print(acl.check_permission("user1", doc, "delete")) # False
print(acl.check_permission("user2", doc, "read")) # False
实际案例:Web API权限控制
结合Flask/FastAPI的完整示例:
from flask import Flask, request, jsonify, g
from functools import wraps
import jwt
from datetime import datetime, timedelta
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'
# 权限配置
PERMISSIONS = {
'read_users': '查看用户列表',
'create_users': '创建用户',
'delete_users': '删除用户',
'view_reports': '查看报表',
}
ROLES = {
'admin': ['read_users', 'create_users', 'delete_users', 'view_reports'],
'manager': ['read_users', 'view_reports'],
'operator': ['read_users', 'create_users'],
}
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
token = request.headers.get('Authorization')
if not token:
return jsonify({'error': '缺少token'}), 401
try:
# 解析JWT token
payload = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
g.user = payload
except:
return jsonify({'error': '无效的token'}), 401
return f(*args, **kwargs)
return decorated_function
def require_permission(permission):
def decorator(f):
@wraps(f)
@login_required
def decorated_function(*args, **kwargs):
user_role = g.user.get('role')
user_permissions = ROLES.get(user_role, [])
if permission not in user_permissions:
return jsonify({'error': '权限不足'}), 403
return f(*args, **kwargs)
return decorated_function
return decorator
@app.route('/api/users', methods=['GET'])
@require_permission('read_users')
def get_users():
return jsonify({'users': ['user1', 'user2']})
@app.route('/api/users', methods=['POST'])
@require_permission('create_users')
def create_user():
return jsonify({'message': '用户创建成功'})
# 登录API - 获取token
@app.route('/api/login', methods=['POST'])
def login():
username = request.json.get('username')
password = request.json.get('password')
# 验证用户凭证(简化示例)
if username == 'admin' and password == 'admin123':
token = jwt.encode({
'username': username,
'role': 'admin',
'exp': datetime.utcnow() + timedelta(hours=24)
}, app.config['SECRET_KEY'])
return jsonify({'token': token})
return jsonify({'error': '用户名或密码错误'}), 401
if __name__ == '__main__':
app.run(debug=True)
推荐的最佳实践
-
存储方案:
- 小项目:使用
SQLite+ 简单的角色表 - 大项目:使用
PostgreSQL+ 完整的RBAC表结构
- 小项目:使用
-
数据库表结构示例:
-- 用户表
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50) UNIQUE,
role_id INT
);
-- 角色表
CREATE TABLE roles (
id INT PRIMARY KEY,
name VARCHAR(50) UNIQUE,
description TEXT
);
-- 权限表
CREATE TABLE permissions (
id INT PRIMARY KEY,
name VARCHAR(50) UNIQUE,
description TEXT
);
-- 角色-权限关联表
CREATE TABLE role_permissions (
role_id INT REFERENCES roles(id),
permission_id INT REFERENCES permissions(id),
PRIMARY KEY (role_id, permission_id)
);
-- 用户-额外权限表(可选,用于特殊情况)
CREATE TABLE user_permissions (
user_id INT REFERENCES users(id),
permission_id INT REFERENCES permissions(id),
PRIMARY KEY (user_id, permission_id)
);
- 权限设计原则:
- 最小权限原则:只给用户必要的最小权限
- 权限分离:不要把所有权限给一个人
- 定期审查:定期检查权限分配是否合理
选择哪种方案取决于你的具体需求:
- 简单应用:使用角色控制足够了
- 复杂业务:需要考虑ACL或ABAC(基于属性的访问控制)
- Web框架:尽量使用框架内置的权限系统