Flask权限管理
权限管理功能的实现可以分为以下几个小块:
1,新建数据库表Role,里面包括id(Integer,主键)name(String),permission(Integer),default(boolean)。users是指向User模型的对外关系,反向赋给User模型一个role属性,这样就可以同郭User.role来访问Role模型,这样就创建了数据库之间的关系。模型里面还定义了一个静态方法(@staticmethod,可以直接通过类访问这个方法而不需要创建实例之后才能访问这个方法),它的作用是初始化Role数据表中的数据,数据库模型代码如下:
class Role(db.Model):
# 定义Role的数据库模型
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
# 该用户角色名称
name = db.Column(db.String(64), unique=True)
# 该用户角色对应的权限
permissions = db.Column(db.Integer)
# 该用户角色是否为默认
default = db.Column(db.Boolean, default=False, index=True)
# 角色为该用户角色的所有用户
users = db.relationship('User', backref='role', lazy='dynamic') @staticmethod
def insert_role():
roles = {
'STAFF': (Permission.ONLY_QUERY, True),
'HIGH_STAFF': (Permission.ONLY_QUERY|
Permission.FORBID, False),
'LEADER': (Permission.ONLY_QUERY|
Permission.FORBID|
Permission.ASSIGN, False),
'ADMINISTATOR': (0x0f, False)
}#除了onlyquery之外,其他的都是模式false
for r in roles:
role = Role.query.filter_by(name=r).first()
if role is None:
# 如果用户角色没有创建: 创建用户角色
role = Role(name=r)
role.permissions = roles[r][0]
role.default = roles[r][1]
db.session.add(role)
db.session.commit() def __repr__(self):
return '<Role %r>' % self.name
Permission类代码如下:
class Permission:
ONLY_QUERY = 0x01#仅查询
FORBID = 0x03#封号
ASSIGN= 0x07#分配行号
ADMINISTRATOR = 0x0f#这个权限要异或
2,授予用户权限:在User模型中添加role的属性
class User(UserMixin,db.Model):
__tablename__ = 'users'
id = db.Column(db.SmallInteger,primary_key=True,nullable=False)#这个字段必须是id,否则无法完成登录验证
username = db.Column(db.String(64))
password_hash = db.Column(db.String(128))
email = db.Column(db.String(64))
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
config_content = config[os.getenv('FLASK_CONFIG') or 'default']
因为User模型有role的属性,可以通过User.role来获取Role数据库中的内容,所以我们的思路是直接通过这一特性进行操作,直接在User模型中的初始化方法中实现默认权限的赋予,是管理员给管理员权限,不是给默认的用户权限。
def __init__(self,**kwargs):
super(User,self).__init__(**kwargs)
#继承了父类的初始化方法,super等价于UserMixin
self.role = kwargs['role_id']
if self.role is None:
if self.email == self.config_content.ADMINS:
#验证email是否为设置的管理员的email
self.role = Role.query.filter_by(permissions=0xff).first()
if self.role is None:
#如果经过了上一步权限还为空,就给个默认的User权限
self.role = Role.query.filter_by(default=True).first()
第4行是管理员为普通员工注册的时候提供的权限,如果是博客权限为空的用户,即刚注册的用户,可以删除第4行,若是用户冲了一个尊贵的会员就需要单独赋予权限了,所以我们可以在User模型里创建一个修改权限的方法,需要的时候调用就可以。
3,用它来对用户进行限制:
3.1,写一个用来判断用户权限的方法,传入用户需要的权限,进行验证,符合返回True,否则为False。这个方法在User模型里面:
def can(self,permissions):
#这个方法用来传入一个权限来核实用户是否有这个权限,返回bool值
return self.role is not None and\
(self.role.permissions & permissions) == permissions def is_administrator(self):
#因为常用所以单独写成一个方法以方便调用,其它权限也可以这样写
return self.can(Permission.ADMINISTRATOR)
3.2 将上面方法写入修饰函数中
#encoding:utf8 from functools import wraps
from flask import abort
from flask_login import current_user
from app.models import Permission def permission_required(permission):
def decorator(f):
@wraps(f)
def decorated_function(*args,**kwargs):
if not current_user.can(permission):
abort(403)
return f(*args, **kwargs)
return decorated_function
return decorator def admin_required(f):
return permission_required(Permission.ADMINISTRATOR)(f)
3.3 用修饰函数对有权限要求的路由进行修饰:
@main.route('/forbid',methods=['GET','POST'])
@login_required
@permission_required(Permission.FORBID)
def forbid():
return 'Hello World'
4新用户注册:
在view中添加如下代码:
##注册
@main.route('/register',methods=['GET','POST'])
@login_required
@permission_required(Permission.ASSIGN)
def register():
form = RegisterationForm()
if form.validate_on_submit():
register_judge_obj = register_judge(form.permission.data)
role_id = register_judge_obj.judge()
user = User(username=form.username.data,password=form.password.data,email=form.email.data,role_id = role_id)
db.session.add(user)
db.session.commit()
return redirect(url_for('main.login'))
return render_template('register.html',form=form)
其中调用的register_judge类代码为
# -*- coding: utf-8 -*-
from app.models import Role class register_judge: def __init__(self,permission_id):
self.permission_id = permission_id def judge(self):
if self.permission_id == '':
role_id = Role.query.filter_by(id=4).first()
elif self.permission_id == '':
role_id = Role.query.filter_by(id=3).first()
elif self.permission_id == '':
role_id = Role.query.filter_by(id=1).first()
else:
role_id = Role.query.filter_by(default=True).first()
return role_id
实际操作过程中遇到的坑:
1,权限存入数据库中数值改变:它其实是以2进制的方式来处理的
0b00000001
0b00000010
0b00000100
0b10000000
如果只是第一个权限,它的值为1
如果是第二个权限(0b00000001|0b00000010)即0b00000011,即3
第三个(0b00000010|0b00000010|0b00000010)即0b00000111即7
以此类推
它并不是以10进制来计算的
2,装饰函数的理解存在问题。
Flask权限管理的更多相关文章
- Android权限管理之RxPermission解决Android 6.0 适配问题
前言: 上篇重点学习了Android 6.0的运行时权限,今天还是围绕着Android 6.0权限适配来总结学习,这里主要介绍一下我们公司解决Android 6.0权限适配的方案:RxJava+RxP ...
- Android权限管理之Android 6.0运行时权限及解决办法
前言: 今天还是围绕着最近面试的一个热门话题Android 6.0权限适配来总结学习,其实Android 6.0权限适配我们公司是在今年5月份才开始做,算是比较晚的吧,不过现在Android 6.0以 ...
- Android权限管理之Permission权限机制及使用
前言: 最近突然喜欢上一句诗:"宠辱不惊,看庭前花开花落:去留无意,望天空云卷云舒." 哈哈~,这个和今天的主题无关,最近只要不学习总觉得生活中少了点什么,所以想着围绕着最近面试过 ...
- SpringMVC+Shiro权限管理【转】
1.权限的简单描述 2.实例表结构及内容及POJO 3.Shiro-pom.xml 4.Shiro-web.xml 5.Shiro-MyShiro-权限认证,登录认证层 6.Shiro-applica ...
- Android6.0运行时权限管理
自从Android6.0发布以来,在权限上做出了很大的变动,不再是之前的只要在manifest设置就可以任意获取权限,而是更加的注重用户的隐私和体验,不会再强迫用户因拒绝不该拥有的权限而导致的无法安装 ...
- Oracle 表空间和用户权限管理
一. 表空间 Oracle数据库包含逻辑结构和物理结构. 数据库的物理结构指的是构成数据库的一组操作系统文件. 数据库的逻辑结构是指描述数据组织方式的一组逻辑概念以及它们之间的关系. 表空间是数据库逻 ...
- [Django]用户权限学习系列之权限管理界面实现
本系列前三章: http://www.cnblogs.com/CQ-LQJ/p/5604331.htmlPermission权限基本操作指令 http://www.cnblogs.com/CQ-LQJ ...
- [Django]用户权限学习系列之设计自有权限管理系统设计思路
若在阅读本片文章遇到权限操作问题,请查看本系列的前两章! http://www.cnblogs.com/CQ-LQJ/p/5609690.html和http://www.cnblogs.com/CQ- ...
- 我的MYSQL学习心得(十三) 权限管理
我的MYSQL学习心得(十三) 权限管理 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...
随机推荐
- 第十五篇:关于TCP通信程序中数据的传递格式
前言 在之前的回射程序中,实现了字符串的传递与回射.幸运的是,字符串的传递不用担心不同计算机类型的大小端匹配问题,然而,如果传递二进制数据,这就是一个要好好考虑的问题.在客户端和服务器使用不同的字节序 ...
- C++异常 调用abort()
以一个计算两个数的调和平均数的函数为例.两个数的调和平均数的定义是:这两个数倒数的平均值的倒数,因此表达式为:1.0 * x * y / (x + y)如果y是x的负值,则上述公式将导致被零除——一种 ...
- Set集合遍历方式
for(String str : set) { System.out.println(str); } for (Iterator iter = set.iterator(); iter.hasNext ...
- x64dbg使用心得
使用ScyllaHide插件时 注意一下事项 xdbg64设置里启动 附加必须第一次断下在 系统断点 然后再启用ScyllaHide. 停止调试 脱离时.必须关闭ScyllaHide 否则会报异常 x ...
- 《转》python学习(4)对象
转自http://www.cnblogs.com/BeginMan/p/3160044.html 一.学习目录 1.pyhton对象 2.python类型 3.类型操作符与内建函数 4.类型工厂函数 ...
- poj_2112 网络最大流+二分法
题目大意 有K台挤奶机和C头奶牛,都被视为物体,这K+C个物体之间存在路径.给出一个 (K+C)x(K+C) 的矩阵A,A[i][j]表示物体i和物体j之间的距离,有些物体之间可能没有直接通路. ...
- ubuntu 安装nfs 服务
1. 安装nfs服务软件 (1)服务器端 $sudo apt-get install nfs-kernel-server rpcbind (2)客户端 (可以省略) $sudo apt-get in ...
- vux版本升级
一开始用的笨办法, 先卸载npm uninstall vux --save; 然后在安装npm install vux --save; 卸载的还是蛮快的,安装是在下班的时候,让电脑待机2个小时,第二 ...
- WCF(一) 创建第一个WCF
定义服务契约-创建宿主程序-创建客户端程序访问服务 namespace HelloService { /// <summary> /// 服务契约 /// </summary> ...
- Linux Git服务器安装
① 安装 Git ② 服务器端创建 git 用户,用来管理 Git 服务,并为 git 用户设置密码 ③ 服务器端创建 Git 仓库 ④ 客户端 clone 远程仓库 ⑤ 客户端创建 SSH 公钥和私 ...