Python案例怎么分配用户权限?

wen python案例 18

本文目录导读:

Python案例怎么分配用户权限?

  1. 基于角色的权限控制(RBAC) - 最常用
  2. 基于位运算的权限控制 - 高性能
  3. 使用第三方库 - Django的权限系统
  4. ACL(访问控制列表) - 细粒度控制
  5. 实际案例:Web API权限控制
  6. 推荐的最佳实践

在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)

推荐的最佳实践

  1. 存储方案

    • 小项目:使用SQLite + 简单的角色表
    • 大项目:使用PostgreSQL + 完整的RBAC表结构
  2. 数据库表结构示例

-- 用户表
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)
);
  1. 权限设计原则
    • 最小权限原则:只给用户必要的最小权限
    • 权限分离:不要把所有权限给一个人
    • 定期审查:定期检查权限分配是否合理

选择哪种方案取决于你的具体需求:

  • 简单应用:使用角色控制足够了
  • 复杂业务:需要考虑ACL或ABAC(基于属性的访问控制)
  • Web框架:尽量使用框架内置的权限系统

抱歉,评论功能暂时关闭!