Flask Bootstrap 后台权限管理方案

发布于:2025-08-03 ⋅ 阅读:(13) ⋅ 点赞:(0)

下面是一个基于 Flask 和 Bootstrap 的后台权限管理方案,包含用户认证、角色管理和权限控制等功能。

核心组件

  1. Flask - 作为后端框架
  2. Bootstrap - 前端UI框架
  3. Flask-Login - 用户会话管理
  4. Flask-SQLAlchemy - 数据库ORM
  5. Flask-WTF - 表单处理
  6. Flask-Principal 或自定义装饰器 - 权限控制

数据库模型设计

from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin

db = SQLAlchemy()

# 用户-角色 多对多关联表
user_roles = db.Table('user_roles',
    db.Column('user_id', db.Integer, db.ForeignKey('users.id')),
    db.Column('role_id', db.Integer, db.ForeignKey('roles.id'))
)

# 角色-权限 多对多关联表
role_permissions = db.Table('role_permissions',
    db.Column('role_id', db.Integer, db.ForeignKey('roles.id')),
    db.Column('permission_id', db.Integer, db.ForeignKey('permissions.id'))
)

class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    email = db.Column(db.String(64), unique=True, index=True)
    password_hash = db.Column(db.String(128))
    active = db.Column(db.Boolean, default=True)
    roles = db.relationship('Role', secondary=user_roles,
                           backref=db.backref('users', lazy='dynamic'))
    
    def set_password(self, password):
        self.password_hash = generate_password_hash(password)
        
    def check_password(self, password):
        return check_password_hash(self.password_hash, password)
    
    def has_role(self, role_name):
        return any(role.name == role_name for role in self.roles)
    
    def has_permission(self, permission_name):
        return any(permission.name == permission_name 
                  for role in self.roles 
                  for permission in role.permissions)

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    description = db.Column(db.String(128))
    permissions = db.relationship('Permission', secondary=role_permissions,
                                backref=db.backref('roles', lazy='dynamic'))

class Permission(db.Model):
    __tablename__ = 'permissions'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    description = db.Column(db.String(128))
    endpoint = db.Column(db.String(128))  # 对应的路由端点

权限控制实现

方案1: 使用装饰器

from functools import wraps
from flask import abort
from flask_login import current_user

def permission_required(permission_name):
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            if not current_user.has_permission(permission_name):
                abort(403)  # 无权限
            return f(*args, **kwargs)
        return decorated_function
    return decorator

def admin_required(f):
    return permission_required('admin')(f)

方案2: 使用 Flask-Principal

from flask_principal import Principal, Permission, RoleNeed

principal = Principal()
admin_permission = Permission(RoleNeed('admin'))
editor_permission = Permission(RoleNeed('editor'))

# 在视图函数中使用
@app.route('/admin')
@admin_permission.require()
def admin():
    return render_template('admin.html')

路由和视图示例

from flask import render_template, redirect, url_for, flash
from flask_login import login_user, logout_user, login_required
from .forms import LoginForm, RegistrationForm

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user and user.check_password(form.password.data):
            login_user(user, remember=form.remember_me.data)
            flash('登录成功', 'success')
            return redirect(url_for('dashboard'))
        flash('用户名或密码错误', 'danger')
    return render_template('login.html', form=form)

@app.route('/logout')
@login_required
def logout():
    logout_user()
    flash('您已登出', 'info')
    return redirect(url_for('login'))

@app.route('/dashboard')
@login_required
def dashboard():
    return render_template('dashboard.html')

@app.route('/admin/users')
@login_required
@permission_required('user_management')
def user_management():
    users = User.query.all()
    return render_template('admin/users.html', users=users)

Bootstrap 后台模板结构

templates/
├── base.html            # 基础模板
├── auth/
│   ├── login.html       # 登录页面
│   └── register.html    # 注册页面
├── admin/
│   ├── dashboard.html   # 控制面板
│   ├── users.html       # 用户管理
│   ├── roles.html       # 角色管理
│   └── permissions.html # 权限管理
└── partials/
    ├── _header.html     # 顶部导航
    ├── _sidebar.html    # 侧边栏菜单
    └── _footer.html     # 页脚

权限动态菜单示例

_sidebar.html 中根据权限动态显示菜单:

<div class="sidebar">
    <ul class="nav flex-column">
        <li class="nav-item">
            <a class="nav-link" href="{{ url_for('dashboard') }}">
                <i class="fas fa-tachometer-alt"></i> 控制面板
            </a>
        </li>
        
        {% if current_user.has_permission('user_management') %}
        <li class="nav-item">
            <a class="nav-link" href="{{ url_for('user_management') }}">
                <i class="fas fa-users"></i> 用户管理
            </a>
        </li>
        {% endif %}
        
        {% if current_user.has_permission('role_management') %}
        <li class="nav-item">
            <a class="nav-link" href="{{ url_for('role_management') }}">
                <i class="fas fa-user-tag"></i> 角色管理
            </a>
        </li>
        {% endif %}
    </ul>
</div>

初始化权限数据

可以创建一个命令来初始化基本角色和权限:

import click
from flask.cli import with_appcontext

@click.command('init-permissions')
@with_appcontext
def init_permissions():
    """初始化权限系统"""
    # 创建基本权限
    permissions = [
        ('dashboard_access', '访问控制面板', 'dashboard'),
        ('user_management', '用户管理', 'user_management'),
        ('role_management', '角色管理', 'role_management'),
        ('permission_management', '权限管理', 'permission_management'),
    ]
    
    for name, desc, endpoint in permissions:
        if not Permission.query.filter_by(name=name).first():
            perm = Permission(name=name, description=desc, endpoint=endpoint)
            db.session.add(perm)
    
    # 创建基本角色
    if not Role.query.filter_by(name='admin').first():
        admin_role = Role(name='admin', description='超级管理员')
        admin_role.permissions = Permission.query.all()
        db.session.add(admin_role)
    
    if not Role.query.filter_by(name='user').first():
        user_role = Role(name='user', description='普通用户')
        dashboard_perm = Permission.query.filter_by(name='dashboard_access').first()
        if dashboard_perm:
            user_role.permissions.append(dashboard_perm)
        db.session.add(user_role)
    
    db.session.commit()
    print("权限系统初始化完成")

安全建议

  1. 使用 HTTPS
  2. 密码哈希存储 (如 bcrypt)
  3. CSRF 保护
  4. 限制登录尝试次数
  5. 敏感操作需要重新验证密码
  6. 定期审计权限分配

这个方案提供了完整的 Flask + Bootstrap 后台权限管理系统的基础架构,可以根据实际需求进行扩展和定制