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学习心得(四) ...
随机推荐
- Python 调用外部命令
python 可以使用 os 模块来调用外部的 Linux Shell 命令,常用的方法如下: os.system():结果输出在终端上,捕获不到os.popen() : 结果返回一个对象,即标准输出 ...
- vs2008设置dll、lib库的输出路径
vs2008中,有些项目上的功能是要生产库文件给其他项目调用的,以下是一些设置库文件(x.dll和x.lib)输出路径的方法. 设置x.dll 输出路径方法是在右键项目的"属性"- ...
- 《C++ Primer Plus》第10章 对象和类 学习笔记
面向对象编程强调的是程序如何表示数据.使用 OOP 方法解决编程问题的第一步是根据它与程序之间的接口来描述数据,从而指定如何使用数据.然后,设计一个类来实现该接口.一般来说,私有数据成员存储信息,公有 ...
- LeetCode——Best Time to Buy and Sell Stock III
Description: Say you have an array for which the ith element is the price of a given stock on day i. ...
- 简单的网络爬虫程序(Web Crawlers)
程序比较简单,但是能体现基本原理. package com.wxisme.webcrawlers; import java.io.*; import java.net.*; /** * Web Cra ...
- 腾讯云CMQ消息队列在Linux环境下的使用
版权声明:本文由李少华原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/76 来源:腾云阁 https://www.qclou ...
- 《转载》struts旅程《1》
struts简介 Struts是Apache软件基金会(ASF)赞助的一个开源项目.它最初是jakarta项目中的一个子项目,并在2004年3月成为ASF的顶级项目.它通过采用JavaServlet/ ...
- 【BZOJ2157】旅游 树链剖分+线段树
[BZOJ2157]旅游 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本 ...
- android异常:Can not perform this action after onSaveInstanc
extends:http://zhiweiofli.iteye.com/blog/1539467 本人某个android项目开发阶段一直运行良好,直到上线前夕,在某款跑着android 4.03系统的 ...
- 【MySQL案例】error.log的Warning:If a crash happens thisconfiguration does not guarantee that the relay lo(转)
标签: 1.1.1. If a crash happens thisconfiguration does not guarantee that the relay log info will be c ...