Flask-Login + 角色权限:一套可扩展的访问控制
拒绝在每个视图里手写 if role != admin,把权限判断收敛到装饰器与服务层。
Flask-Login + 角色权限:一套可扩展的访问控制
权限代码最怕两件事:判断散落在各处,以及新增角色时到处补条件。
用户模型的三件事
- 密码哈希:只存哈希,永不存明文
- 角色标识:普通用户、会员、管理员
- 权益判断:会员是否在有效期
把权益判断写成属性,模板与服务层都能复用:
@property
def membership_active(self):
if self.is_admin:
return True
return self.role == "member" and self.membership_expires_at > now()
装饰器收敛判断
def role_required(*roles):
def decorator(view):
@wraps(view)
@login_required
def wrapped(*args, **kwargs):
if not current_user.has_role(*roles):
raise ForbiddenError()
return view(*args, **kwargs)
return wrapped
return decorator
后台路由统一使用 @admin_required,业务层再做一次权益校验,形成双重保险。
常见坑
- 不要用
is_active作为业务字段,它与 Flask-Login 的接口冲突 - 修改角色时应防止移除最后一个管理员
- 登录跳转参数必须校验,避免开放重定向
权限系统不需要复杂,但必须只有一个判断入口。