为了账号安全,请及时绑定邮箱和手机立即绑定

使用python/flask实现鉴权

标签:
Python

上一篇文章介绍了使用JWT协议来做token认证的功能,继续装逼下去,怎样实现一个鉴权的模块?

假设token认证的功能已经完成,那么设定为每次请求头部中都带上这个token。server端在每次响应请求时都要做一次token的校验,包括两个内容:

  • token是否合法,token是否过期、是否被篡改,token内的信息是否有效

  • 用户是否有权限执行此请求

在python/flash上,这个检验使用decorator实现,会是一个很靠谱的办法,代码简洁性和可读性都很不错。

为认证和鉴权创建数据模型

首先,理清关系,用户-角色-权限,是多对多对多的关系。通过flask-sqlalchemy给这三者创建多对多模型,会是五张表,其中有两张表是多对多连接用的实体表,无ORM模型(根据flask的建议)。

然后,为了实现审计功能(一些删除对象操作之后将造成历史数据无法对应),用户-角色-权限都需要添加valid字段。删除时只设为不可用。

最后,创建一个decorator函数,实现检查token并审核权限的功能。

目标效果是怎样的?

在一个api或函数前,添加此decorator,参数包含它所需要的权限名称。一旦请求执行到此函数,将执行decorator的权限检查。如果认证或鉴权失败,直接走异常处理流程,不会执行请求内容。类似这样:

@auth.PrivilegeAuth(privilegeRequired="userAdmin")
    def get(self):
        """
        get user list or one user info ...
        """

怎么实现

这需要一个带参数的decorator类,需要传参。内部逻辑十分简单,检查token--检查用户--检查角色--检查权限匹配--搞定放行。

ps.抱歉我的英文十分chinglish哈哈。。

auth.py

class PrivilegeAuth(Resource):
    """
    This class is used tobe a decoretor for other methods to check the
    client's privilege by token.
    Your method's 'required privilege' should be set as an argument of this
    decoretor. And this 'required privilege' should have been in the
    'privilege' table.
    If your method's 'required privilege' is one of user's privileges,
    user will be allowed to access the method, otherwise not.
    ps. user's privilege is checked by his token.
    """
    def __init__(self, privilegeRequired):
        # argument 'privilegeRequired' is to set up your method's privilege
        # name
        self.privilegeRequired = privilegeRequired
        super(PrivilegeAuth, self).__init__()    def __call__(self, fn):
        def wrapped(*args, **kwargs):
            try:
                rolesReq = Privilege.getFromPrivilegeName(
                    self.privilegeRequired).roles            except:
                msg = 'wrong privilege setting: privilege (' +\
                    self.privilegeRequired + ') doesnot set in any roles'
                app.logger.error(utils.logmsg(msg))                raise utils.InvalidModuleUsage('wrong privilege setting')            # get user's privileges by his token
            # if token is in body, then:
            # myreqparse = reqparse.RequestParser()
            # myreqparse.add_argument('token')
            # args = myreqparse.parse_args()
            # if token is in headers, then:
            token = request.headers.get('token')            if not token:
                msg = "you need a token to access"
                raise utils.InvalidAPIUsage(msg)
            [userId, roleIdList, msg] = User.tokenAuth(token)            if not userId:
                msg = msg + " when autherization"
                raise utils.InvalidAPIUsage(msg)            else:
                currentUser = User.getValidUser(userId=userId)                if not currentUser:
                    msg = "cannot find user when autherization"
                    raise utils.InvalidAPIUsage(msg)            # user's privilege auth
            for role in currentUser.roles:                for roleReq in rolesReq:                    if role.role_id == roleReq.role_id:                        return fn(*args, **kwargs)

            msg = "Privilege not Allowed."
            app.logger.info(utils.logmsg(msg))            raise utils.InvalidAPIUsage(msg)        return wrapped



作者:茶客furu声
链接:https://www.jianshu.com/p/5b1f69efefdf


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消