MST

星途 面试题库

面试题:Python RESTful API授权机制中的RBAC模型如何在代码中实现

请描述基于角色的访问控制(RBAC)模型的概念,并详细说明在Python开发的RESTful API里,如何使用数据库(如SQLite、MySQL)和框架(如FastAPI)来设计数据结构和编写代码实现RBAC模型,包括角色、权限、用户与角色关联等功能。
18.9万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

基于角色的访问控制(RBAC)模型概念

RBAC是一种广泛应用的访问控制策略,它基于用户在系统中所扮演的角色来管理对资源的访问权限。在RBAC模型中有三个主要元素:

  1. 用户(User):使用系统的个体。
  2. 角色(Role):代表一组权限的集合,一个角色可以被赋予多个权限,一个用户可以拥有多个角色。
  3. 权限(Permission):定义了对特定资源的特定操作,如读取文件、写入数据库记录等。

在Python的FastAPI中使用数据库实现RBAC模型

1. 数据结构设计

以SQLite为例,使用SQLAlchemy库来定义数据库模型,SQLAlchemy同样适用于MySQL等其他数据库。

from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.ext.declarative import declarative_base

# 创建数据库引擎
engine = create_engine('sqlite:///rbac.db')
Session = sessionmaker(bind=engine)
Base = declarative_base()

# 定义权限表
class Permission(Base):
    __tablename__ = 'permissions'
    id = Column(Integer, primary_key=True)
    name = Column(String(50), unique=True)
    description = Column(String(200))

# 定义角色表
class Role(Base):
    __tablename__ = 'roles'
    id = Column(Integer, primary_key=True)
    name = Column(String(50), unique=True)
    permissions = relationship('Permission', secondary='role_permissions')

# 角色 - 权限关联表
class RolePermission(Base):
    __tablename__ = 'role_permissions'
    role_id = Column(Integer, ForeignKey('roles.id'), primary_key=True)
    permission_id = Column(Integer, ForeignKey('permissions.id'), primary_key=True)

# 定义用户表
class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    username = Column(String(50), unique=True)
    roles = relationship('Role', secondary='user_roles')

# 用户 - 角色关联表
class UserRole(Base):
    __tablename__ = 'user_roles'
    user_id = Column(Integer, ForeignKey('users.id'), primary_key=True)
    role_id = Column(Integer, ForeignKey('roles.id'), primary_key=True)

2. FastAPI实现RBAC功能

from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
from typing import List

app = FastAPI()

# 获取数据库会话的依赖项
def get_db():
    db = Session()
    try:
        yield db
    finally:
        db.close()

# 创建用户
@app.post('/users/')
def create_user(username: str, db: Session = Depends(get_db)):
    new_user = User(username=username)
    db.add(new_user)
    db.commit()
    db.refresh(new_user)
    return new_user

# 创建角色
@app.post('/roles/')
def create_role(name: str, db: Session = Depends(get_db)):
    new_role = Role(name=name)
    db.add(new_role)
    db.commit()
    db.refresh(new_role)
    return new_role

# 为角色添加权限
@app.post('/roles/{role_id}/permissions/')
def add_permission_to_role(role_id: int, permission_name: str, db: Session = Depends(get_db)):
    role = db.query(Role).filter(Role.id == role_id).first()
    permission = db.query(Permission).filter(Permission.name == permission_name).first()
    if not role or not permission:
        return {"message": "Role or Permission not found"}
    role.permissions.append(permission)
    db.commit()
    return {"message": "Permission added to role successfully"}

# 为用户添加角色
@app.post('/users/{user_id}/roles/')
def add_role_to_user(user_id: int, role_id: int, db: Session = Depends(get_db)):
    user = db.query(User).filter(User.id == user_id).first()
    role = db.query(Role).filter(Role.id == role_id).first()
    if not user or not role:
        return {"message": "User or Role not found"}
    user.roles.append(role)
    db.commit()
    return {"message": "Role added to user successfully"}

# 检查用户权限
@app.get('/users/{user_id}/has_permission/{permission_name}/')
def check_user_permission(user_id: int, permission_name: str, db: Session = Depends(get_db)):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        return {"message": "User not found"}
    for role in user.roles:
        for permission in role.permissions:
            if permission.name == permission_name:
                return {"has_permission": True}
    return {"has_permission": False}

以上代码展示了在FastAPI应用中,如何使用SQLite数据库(通过SQLAlchemy)来实现RBAC模型的基本功能,包括用户、角色、权限以及它们之间的关联关系,以及如何通过API接口来操作这些数据。对于MySQL数据库,只需修改create_engine的连接字符串即可,其余代码逻辑基本不变。