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

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

基本的flask权限管理

1. 验证字段与密码的存储

权限管理的基础就是验证字段(用户名or邮箱...)以及密码,

所以首先需要考虑验证字段和密码的存储。(这里使用flask-sqlalchemy作为ORM)

model:Userclass User(db.Model):    """用户类"""    id = db.Column(db.Integer, primary_key=True)    # 用户名字符串存储即可    username = db.Column(db.String(164))    # 密码一定要注意    # 密码不允许在数据库中明文存储    password_hash = db.Column(db.String(164))    ......    # 所以需要对用户传入的明文密码进行加密    @property    def password(self):        """        password属性函数        不允许直接读取原始值        """        return "密码不是可读形式!"    @password.setter    def password(self, password):        """        设置密码hash值        """        self.password_hash = werkzeug.security.generate_password_hash(password)    def verify_password(self, password):        """        将用户输入的密码明文与数据库比对        """        return werkzeug.security.check_password_hash(password)

2. 用户权限与角色的设置

我一般将用户权限设置为16进制的值, 而用户角色则是用户权限(16进制的值)的异或(|)运算,

比如我设置以下2个权限:

class Permission:    """    权限表    """    COMMENT = 0x01  # 评论    MODERATE_COMMENT = 0x02  # 移除评论

那么可设置如下角色, 并建立和User的多对一关系:

class Role(db.Model):    """    用户角色    """    id = db.Column(db.Integer, primary_key=True)    # 该用户角色名称    name = db.Column(db.String(164))    # 该用户角色是否为默认    default = db.Column(db.Boolean, default=False, index=True)    # 该用户角色对应的权限    permissions = db.Column(db.Integer)    # 该用户角色和用户的关系    # 角色为该用户角色的所有用户    users = db.relationship('User', backref='role', lazy='dynamic')    @staticmethod    def insert_roles():        """        创建用户角色        """        roles = {            # 定义了两个用户角色(User, Admin)            'User': (Permission.COMMENT, True),            'Admin': (Permission.COMMENT |                      Permission.MODERATE_COMMENT, 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()

现在只需在User里创建一个指向用户角色的外键即可

calss User(db.Model):    ......    role_id = db.Column(db.Integer, db.ForeignKey('role.id'))    ......

flask权限在具体场景中的应用

应用在具体场景, 使用相关扩展就不可避免了

1. 处理登录(flask-login)

对于flask登录,使用flask-login是较为简单的办法,

但是个人感觉flask-login不是很灵活(下面的扩展也是,
毕竟扩展的目的是通用)。<br/>
这里就不具体说明,主要说如何使用flask-login<br/>

用户登录

使用flask-login提供的login_user, current_user

@auth.route('/login/', methods=["POST", "GET"])def login():    """用户登录"""    next = get_redirect_target()    form = LoginForm()    if form.validate_on_submit():        user = User.query.filter_by(username=form.username.data).first()        if user is not None and user.verify_password:            login_user(user)            return redirect_back('default redirect back url', id=current_user.id)        flash("用户名或密码错误!")    return render_template("login.html", form=form, next=next)

用户登出

使用flask-login提供的logout_user

@login_required@auth.route('/logout/')def logout():    """用户登出"""    logout_user()    return redirect("重定向路由")

2. 处理HTTPBasicAuth(flask-httpauth)

可以帮助我们处理一些基本的权限管理,

同flask-login一样, flask-httpauth 也提供了一个login_required装饰器,
通过auth对象调用即可控制用户名, 密码的登录权限控制。

token权限管理

这里比较复杂的地方就是token的权限管理了, 因为此处没有拓展可用(扩展是为了通用性, 但是token不是强制使用的),

都是自己踩坑弄出来的, 写在博客里做一个纪录。

什么是token

token是用户信息(一般是用户id,

具有唯一标识作用)的标识。对用户id进行签名加密(我一般使用itsdangerous模块),
例如:

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer# 此函数为User类的成员函数def generate_auth_token(self):    s = Serializer(        current_app.config['SECRET_KEY'],  # 密钥很重要        expiration  # Token的寿命    )    # 用获取的签名加密用户id信息    return s.dumps({'id': self.id})
为什么需要token

token 一般使用在API的场景中, 此时客户端和服务器端是分离的,

数据信息通过API进行传递, 他人很容易就可以拦截API并获取验证头部的authorization字段,
从而获取用户名和密码(一般是base64进行了加密, 但是很容易被破解), 这样是极不安全的。<br/>
之所以需要验证, 其实就是为了标识这个用户是谁, 而id就是一个最好的标识,
所以通过用户的用户名和密码请求token(这样用户名和密码不会频繁被发送),
用获取的token放在API头部进行传递, 这样即使被拦截,
也不会获取用户的敏感信息(用户名, 密码), 即使token被他人使用,
也会因为token的寿命而使破坏性大大降低。

token的使用: 发送token

token需放在Authorization头部, 采用如下形式发送:

"Basic token"
token的使用: 解析token

依然采用itsdangerous模块, 这里密钥就很重要了,

只有与加密相同的密钥才可以解析token。

# User类的一个静态成员函数@staticmethoddef verify_auth_token(token):    # 获取签名    s = Serializer(current_app.config["SECRET_KEY"])    try:        data = s.loads(token)  # 用签名解析token    except:        return None    # 返回该token标识的用户    return User.query.filter_by(id=data['id'])
基于token的权限管理

这里主要是区别普通用户和管理员用户, 因为有些特定的操作是只有管理员可以进行的。<br/>

1.在User类里添加管理员判断函数 <br/>

def can(self, permission):    # 判断用户是否具备某权限    return self.role is not None and (self.role.permissions & permissions) = permissionsdef is_adminstractor(self):    # 判断用户是否具备管理员权限    return self.can(Permission.COMMENT | Permission.MODERATE_COMMENT)

2.创建管理员权限判断装饰器<br/>

from functools import wrapsfrom flask import request, gdef admin_required(f):    @wraps(f)    def decorator(*args, **kwargs):        token_header = request.headers.get('authorization')        token = token_header[6:]  # 去掉格式中的Basic        if token:            g.current_user = User.verify_auth_token(token)            if g.current_user.is_adminstractor():                return f(*args, **kwargs)            else:                abort(403)    return decorator

然后就可以使用admin_required装饰器进行权限管理了,

这里有个坑提一下就是flask-httpauth会自己添加Basic,
所以使用该扩展的地方就不必考虑token格式的问题了。

总结

flask权限管理比较烦的地方就是如何使不同的权限管理扩展一起工作,

以及使用了扩展以后对于定制自己的东西该如何写,
这时候还是最好去看使用相应扩展的源码, 然后以此为基础, 展开自己的工作吧!

转载地址:http://thbfa.baihongyu.com/

你可能感兴趣的文章
从新浪的分享文本字符串中,分离出@到的好友的方法
查看>>
11-02笔记图
查看>>
visual c++ 2010安装失败导致CRM2015安装失败
查看>>
web项目直接在浏览器上访问不需要带.jsp,直接ip地址加项目名 在web.xml里配置...
查看>>
一步一步使用Ext JS MVC与Asp.Net MVC 3开发简单的CMS后台管理系统之用户管理(3)...
查看>>
1+2+34-5+67-8+9=100?
查看>>
ELK系列~Fluentd对大日志的处理过程~16K
查看>>
安装appium桌面版和命令行版
查看>>
15款经典图表软件推荐 创建最漂亮的图表
查看>>
Python进阶量化交易场外篇4——寻找最优化策略参数
查看>>
5Linux流程控制语句-if、for、while、case语句、计划任务
查看>>
有哪些质量上乘的程序员必关注的网站或论坛
查看>>
正则表达式
查看>>
我理解的几种字符编码方式
查看>>
BZOJ-4706 B君的多边形 OEIS
查看>>
报错之解决方案1--找不到文件或文件夹
查看>>
spring容器加载完毕做一件事情(利用ContextRefreshedEvent事件)转
查看>>
OFFICE 2007 序列号
查看>>
07-JAVA继承与接口
查看>>
ubuntu15.10下sublime text3 无法输入中文解决办法
查看>>