基于JWT的权限校验中的坑

  • 2021-03-12
  • 2,878
  • 1

一、访问令牌中存储的数据

create_access_token()用来创建令牌

access_tocken = create_access_token(identity=userObj)
res_data = {'token': access_tocken}

jwt_required()这是一个装饰器,用来保护flask节点

在被保护的方法中获取令牌信息可以使用get_jwt_claims()。在实际操作过程中发现create_access_token中的传参不可以为对象,只能为基础数据类型。但在有用户管理的场景中,某些方法往往需要在被保护方法中核验用户角色从而校验是否能够进行相关操作,而不是只校验用户是否登录,因此希望token中的信息包含用户相关的一系列信息,从而减少对数据库的读取操作。

user_claims_loader() 可以拓展create_access_token,使其可以接受对象作为参数。

定义jwt.user_claims_loader装饰器,该装饰器会在调用create_access_token函数时自动被调用,
user_claims_loader的参数就是传递给 create_access_token的参数
user_claims_loader返回的数据会被保存到jwt 中,作为claims存在

class User:
    def __init__(self, username, usertype, nickname):
        self.username = username
        self.usertype = usertype
        self.nickname = nickname

# 存储数据
@app_jwt.user_claims_loader
def add_claims_to_access_token(user):
    return {
        'username': user.username,
        'usertype': user.usertype,
        'nickname': user.nickname
    }

userObj = User(username, usertype, nickname)
access_tocken = create_access_token(identity=userObj)

在方法体中可以通过下面方法重新获取存储的对应的User对象

current_user = get_jwt_claims()

二、token的校验方式

在实际开发中有这么一种场景:某页面需要权限进行访问,只能页面所有者能进行访问,但是同时他需要实现分享功能,拥有链接的人也有权限查看该页面。但是只拥有链接的人因为不一定进行过登录验证,可能只是简单的浏览器打开,get请求之下不携带含有token的请求头或者cookie。查看文档之后发现token可以设置添加在请求头,json数据格式中,或者链接参数中(适用于get方法)。

# 基于字符串的token校验优先,则无权账号也可以通过访问携带token的链接访问
app.config["JWT_TOKEN_LOCATION"] = ["query_string", "headers", "cookies", "json"]
app.config['JWT_ACCESS_COOKIE_NAME'] = "Admin-Token"
app.config['JWT_QUERY_STRING_NAME'] = "token"
app.config['JWT_JSON_KEY'] = "token"

另外需要提及,设定location时顺序有讲究,经过试验有优先之分,如果不将”query_string”设置在第一位,那么登录用户A在访问登录用户B分享的链接时,会优先使用A自己的token校验导致无法访问,而如果设置”query_string”优先,那么则会以链接中的token令牌为优先校验的对象,即以B的权限去验证。分享时需要在链接中加入token参数如:https://www.clingclang.cn?token=xxxxxxx 则不登录用户访问该链接也可以通过权限校验。

但由此又产生了问题,一来链接过长,二来token在分享时直接暴露,看起来就不太安全的样子。于是乎又顺手撘了一个长短链接转化功能,再生成含令牌链接的同时数据库建立映射关系,生成表面不含token的短链。那么就可以分享短链出去,后端再根据数据库重新做重定向访问到原来的资源!映射前后 ↓

 

评论

苟活时长: Copyright © 2019-2020 OJO