博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Flask权限管理
阅读量:6804 次
发布时间:2019-06-26

本文共 5234 字,大约阅读时间需要 17 分钟。

权限管理功能的实现可以分为以下几个小块:

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 '
' % 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:utf8from functools import wrapsfrom flask import abortfrom flask_login import current_userfrom app.models import Permissiondef 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 decoratordef 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 Roleclass register_judge:    def __init__(self,permission_id):        self.permission_id = permission_id    def judge(self):        if self.permission_id == '1':            role_id = Role.query.filter_by(id=4).first()        elif self.permission_id == '2':            role_id = Role.query.filter_by(id=3).first()        elif self.permission_id == '3':            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,装饰函数的理解存在问题。

转载于:https://www.cnblogs.com/wuxie1989/p/6439618.html

你可能感兴趣的文章
桌面支持--512-Rear chassis fan not detected
查看>>
Django 开源相册组件介绍 django-photologue
查看>>
IntelliJ IDEA 14 创建Web项目
查看>>
Redis server命令
查看>>
PeerConnection
查看>>
关于ext-js 中的自定义校验
查看>>
服务端response对象属性和方法
查看>>
护眼色
查看>>
Understanding Java Lambdas
查看>>
Java_基本数据类型
查看>>
Linux下安装JDK
查看>>
axis2报错:The following error occurred during schema generation: null
查看>>
Spring boot ServletRequest 修改header
查看>>
查看CentOS版本信息
查看>>
GPU应用程序Attach调试记录
查看>>
JS this指向详解
查看>>
es6 let使用总结
查看>>
使用Web Uploader实现文件上传
查看>>
关于原生 JS
查看>>
读Zepto源码之Gesture模块
查看>>