Flask权限管理

摘要:
def__init__:super.__init__#继承了父类的初始化方法,super等价于UserMixinself.role=kwargs['role_id']ifself.roleisNone:ifself.email==self.config_content.ADMINS:#验证email是否为设置的管理员的emailself.role=Role.query.filter_by.first()ifself.roleisNone:#如果经过了上一步权限还为空,就给个默认的User权限self.role=Role.query.filter_by.first()第4行是管理员为普通员工注册的时候提供的权限,如果是博客权限为空的用户,即刚注册的用户,可以删除第4行,若是用户冲了一个尊贵的会员就需要单独赋予权限了,所以我们可以在User模型里创建一个修改权限的方法,需要的时候调用就可以。

权限管理功能的实现可以分为以下几个小块:
1,新建数据库表Role,里面包括id(Integer,主键)name(String),permission(Integer),default(boolean)。users是指向User模型的对外关系,反向赋给User模型一个role属性,这样就可以同郭User.role来访问Role模型,这样就创建了数据库之间的关系。模型里面还定义了一个静态方法(@staticmethod,可以直接通过类访问这个方法而不需要创建实例之后才能访问这个方法),它的作用是初始化Role数据表中的数据,数据库模型代码如下:

classRole(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
    definsert_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 inroles:
            role = Role.query.filter_by(name=r).first()
            if role isNone:
                #如果用户角色没有创建: 创建用户角色
                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类代码如下:

classPermission:
    ONLY_QUERY = 0x01#仅查询
    FORBID = 0x03#封号
    ASSIGN= 0x07#分配行号
    ADMINISTRATOR = 0x0f#这个权限要异或

2,授予用户权限:在User模型中添加role的属性

classUser(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 isNone:
            if self.email ==self.config_content.ADMINS:
            #验证email是否为设置的管理员的email
                self.role = Role.query.filter_by(permissions=0xff).first()
            if self.role isNone:
            #如果经过了上一步权限还为空,就给个默认的User权限
                self.role = Role.query.filter_by(default=True).first()

第4行是管理员为普通员工注册的时候提供的权限,如果是博客权限为空的用户,即刚注册的用户,可以删除第4行,若是用户冲了一个尊贵的会员就需要单独赋予权限了,所以我们可以在User模型里创建一个修改权限的方法,需要的时候调用就可以。

3,用它来对用户进行限制:
3.1,写一个用来判断用户权限的方法,传入用户需要的权限,进行验证,符合返回True,否则为False。这个方法在User模型里面:

    defcan(self,permissions):
    #这个方法用来传入一个权限来核实用户是否有这个权限,返回bool值
        return self.role is not None and(self.role.permissions & permissions) ==permissions

    defis_administrator(self):
    #因为常用所以单独写成一个方法以方便调用,其它权限也可以这样写
        return self.can(Permission.ADMINISTRATOR)

3.2 将上面方法写入修饰函数中

#encoding:utf8

from functools importwraps
from flask importabort
from flask_login importcurrent_user
from app.models importPermission

defpermission_required(permission):
    defdecorator(f):
        @wraps(f)
        def decorated_function(*args,**kwargs):
            if notcurrent_user.can(permission):
                abort(403)
            return f(*args, **kwargs)
        returndecorated_function
    returndecorator

defadmin_required(f):
    return permission_required(Permission.ADMINISTRATOR)(f)

3.3 用修饰函数对有权限要求的路由进行修饰:

@main.route('/forbid',methods=['GET','POST'])
@login_required
@permission_required(Permission.FORBID)
defforbid():
    return 'Hello World'

4新用户注册:

在view中添加如下代码:

##注册
@main.route('/register',methods=['GET','POST'])
@login_required
@permission_required(Permission.ASSIGN)
defregister():
    form =RegisterationForm()
    ifform.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 importRole

classregister_judge:

    def __init__(self,permission_id):
        self.permission_id =permission_id

    defjudge(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,装饰函数的理解存在问题。

免责声明:文章转载自《Flask权限管理》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇v-for元素绑定事件代理携程开源框架Apollo基础学习(一)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

前端与后端的数据交互(jquery ajax+python flask)

前端与后端的数据交互,最常用的就是GET、POST,比较常用的用法是:提交表单数据到后端,后端返回json 前端的数据发送与接收1)提交表单数据2)提交JSON数据 后端的数据接收与响应1)接收GET请求数据2)接收POST请求数据3)响应请求 前端的数据发送与接收 1. 提交表单数据 # GET请求 var data = { "name":...

在Ubuntu下部署Flask项目

FlaskDemo 命名为test.py # coding=utf-8 from flask import Flask app = Flask(__name__) @app.route("/") def index(): return "test" if __name__ == '__main__': app.debug = True...

AttributeError: module 'DBBase' has no attribute 'DBBase'

AttributeError: module 'DBBase' has no attribute 'DBBase' pycharm不会将当前文件目录自动加入自己的sourse_path。右键make_directory as-->Sources Root将当前工作的文件夹加入source_path就可以了。 还有一点:models加一个点,表示同级目...

基于Flask的 api(四)

restful安全认证 Flask-HTTPAuth是一个简单的扩展,它简化了使用Flask路由的HTTP身份验证的使用 安装Flask-HTTPAuth pip install Flask-HTTPAuth 认证方式有 Basic 、Digest、token 1.Basic认证 使用HTTP基本身份验证来保护路由 fromflask import Fla...

基于Flask的 api(三)

使用flask的RESTful扩展库 flask-restful 安装 pip install flask-restful eg: 最简单的api fromflask import Flask fromflask_restful import Api, Resource app =Flask(__name__) api =Api(app) classH...

12.1 flask基础之简单实用

一、Flask介绍(轻量级的框架,非常快速的就能把程序搭建起来) Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,...