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学习心得(四) ...
随机推荐
- iOS - UITableView判断reloadData加载数据已经结束
问题: stackoverflow上有人提问这样的问题 http://stackoverflow.com/questions/16071503/how-to-tell-when-uitableview ...
- KVC与Runtime结合使用(案例)及其底层原理
一.KVC 的用法和实践 用法 KVC(Key-value coding)键值编码,顾名思义.额,简单来说,是可以通过对象属性名称(Key)直接给属性值(value)编码(coding)“编码”可以理 ...
- Vue基础---->vue-router的使用(一)
用 Vue.js + vue-router 创建单页应用,是非常简单的.使用 Vue.js 时,我们就已经把组件组合成一个应用了,当你要把 vue-router 加进来,只需要配置组件和路由映射,然后 ...
- MQTT的学习研究(十三) IBM MQTTV3 简单发布订阅实例
使用IBM MQTTv3实现相关的发布订阅功能 MQTTv3的发布消息的实现: package com.etrip.mqttv3; import com.ibm.micro.client.mqttv3 ...
- Excel 2010 如何快速统计一列中相同数值出现的个数 很不错
https://jingyan.baidu.com/article/9113f81b2c16822b3214c785.html 最近经常看到论坛和百度知道的朋友提问关于“excel中如何快速统计一列中 ...
- PHP unlink()函数,删除文件
定义和用法 unlink() 函数删除文件. 若成功,则返回 true,失败则返回 false. 语法 unlink(filename,context) 参数 描述 filename 必需.规定要删除 ...
- js数组的基本用法及数组根据下标(数值或字符)移除元素
1.创建数组 var array = new Array(); var array = new Array(size);//指定数组的长度 var array = new Array(item1,it ...
- shiro框架的学习
1shiro框架是什么:是一个权限控制的框架2shiro框架有什么作用:权限管理,管理那些资源是否需要登录才能访问.控制某些资源需要那些权限才能访问3shiro框架怎样使用: 1在web.xml配置s ...
- Java使用极小的内存完成对超大数据的去重计数,用于实时计算中统计UV
Java使用极小的内存完成对超大数据的去重计数,用于实时计算中统计UV – lxw的大数据田地 http://lxw1234.com/archives/2015/09/516.htm Java使用极小 ...
- python面向对象(类和对象及三大特性)
类和对象是什么 创建类 新式类 和 经典类 面向对象三大特性 继承 封装 多态 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...