Flask Bootstrap 后台权限管理方案
下面是一个基于 Flask 和 Bootstrap 的后台权限管理方案,包含用户认证、角色管理和权限控制等功能。
核心组件
- Flask - 作为后端框架
- Bootstrap - 前端UI框架
- Flask-Login - 用户会话管理
- Flask-SQLAlchemy - 数据库ORM
- Flask-WTF - 表单处理
- Flask-Principal 或自定义装饰器 - 权限控制
数据库模型设计
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixindb = 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_userdef 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_functionreturn decoratordef admin_required(f):return permission_required('admin')(f)
方案2: 使用 Flask-Principal
from flask_principal import Principal, Permission, RoleNeedprincipal = 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("权限系统初始化完成")
安全建议
- 使用 HTTPS
- 密码哈希存储 (如 bcrypt)
- CSRF 保护
- 限制登录尝试次数
- 敏感操作需要重新验证密码
- 定期审计权限分配
这个方案提供了完整的 Flask + Bootstrap 后台权限管理系统的基础架构,可以根据实际需求进行扩展和定制