插件flask_jwt_extended

书接上文flask配置生产环境,我们了解到了:
如何配置flask+uWSGI+nginx的生产环境

接下来我们来看拓展性更强的jwt插件flask_jwt_extended

flask_jwt_extended

安装

> pip3 install Flask-JWT-Extended

什么是Flask-JWT-Extended
之前已经说过jwt是序列化并加密过的json串,那很明显extend则是对之前功能的拓展。那下面我们就该看看拓展的强大之处。
app.py

from flask_jwt_extended import JWTManager

app.config['JWT_SECRET_KEY'] = 'jose'  # token密钥
app.config['JWT_BLACKLIST_ENABLED'] = True  # 黑名单管理
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = ['access', 'refresh']  # 允许将access and refresh tokens加入黑名单
#注册jwt
jwt = JWTManager(app)

接下来,因为此插件剔除了自动生成/auth,我们需要拓展user的功能,生成用户有关的:注册、登录、登出等功能,以及用户令牌认证以及刷新、失效等功能。
user.py

#关联包介绍

#request约束
_user_parser = reqparse.RequestParser()
_user_parser.add_argument('username',
                          type=str,
                          required=True,
                          help="This field cannot be blank."
                          )
_user_parser.add_argument('password',
                          type=str,
                          required=True,
                          help="This field cannot be blank."
                          )
#用户登录
class UserLogin(Resource):
    def post(self):
#从parser获取request资料
        data = _user_parser.parse_args()
#找到用户资料
        user = UserModel.find_by_username(data['username'])
#进行用户认证
        if user and safe_str_cmp(user.password, data['password']):
#生成token,认证令牌和刷新令牌
            access_token = create_access_token(identity=user.id, fresh=True)
            refresh_token = create_refresh_token(user.id)
            return {
                       'access_token': access_token,
                       'refresh_token': refresh_token
                   }, 200
#认证失败
        return {"message": "Invalid Credentials!"}, 401

claims
这是jwt的数据存储机制

jwt = JWTManager(app)
#user_claims_loader定义我们附加到jwt的有效数据
#在每一个收到jwt保护的端口,我们都可以使用get_jwt_claims检索这些数据
#如下所示
@jwt.user_claims_loader
def add_claims_to_jwt(identity):
    if identity == 1:   # instead of hard-coding, we should read from a config file to get a list of admins instead
        return {'is_admin': True}
    return {'is_admin': False}

通过这个示例我们可以模拟用户管理机制,如下对item.py的修改,非管理员用户不可以删除item:
注意下get_jwt_claims,说明在上文。

    @jwt_required
    def delete(self, name):
        claims = get_jwt_claims()
        if not claims['is_admin']:
            return {'message': 'Admin privilege required.'}, 401

        item = ItemModel.find_by_name(name)
        if item:
            item.delete_from_db()
            return {'message': 'Item deleted.'}
        return {'message': 'Item not found.'}, 404

接下来就是一个个介绍特色的时候了:
jwt_optional
官网介绍是,可以可选的保护节点,无论是否发送token,都可以进入节点,然后交给逻辑判断如何处理。比较常见的判定如下:
如果请求中存在访问令牌,则将调用get_jwt_identity()具有访问令牌标识的端点。如果请求中不存在访问令牌,则仍将调用此端点,但 get_jwt_identity()将返回None
示例

class ItemList(Resource):
    @jwt_optional
    def get(self):
        user_id = get_jwt_identity()
        items = [item.json() for item in ItemModel.find_all()]
        if user_id:
            return {'items': items}, 200
        return {
            'items': [item['name'] for item in items],
            'message': 'More data available if you log in.'
        }, 200

create_refresh_token
这个要追溯到create_access_token。一般来说,我们都是将用户权限和用户基本资料存放在这个TOKEN中,但是当用户权限?或者资料变更时,我们就要去刷新用户的资料,或者说当access_token过期了,我们也要去更新access_token。这一部分可以细看Web API与OAuth:既生access token,何生refresh token
其实这只是定义的问题(不过如果不是自己写TOKEN规则,我们要遵守这个定义)。我们在书写create_refresh_token的逻辑时,不在需要验证用户名和密码即达到了这种效果,如果说个人不这么写逻辑,你也看不出来效果,毕竟两种TOKEN其实是一样的。

class TokenRefresh(Resource):
    @jwt_refresh_token_required
    def post(self):
        current_user = get_jwt_identity()
        new_token = create_access_token(identity=current_user, fresh=False)
        return {'access_token': new_token}, 200

这里有另一个概念,令牌的新鲜度fresh=False/True。我们可以根据此处的变更灵活处理一些敏感数据。比如说有些数据只有刚输入用户名和密码时的那段有效认证期才可以使用,当令牌刷新时即判定无效。此处匹配装饰器fresh_jwt_required()
item.py,POST /item/<name>的逻辑变更。

    @fresh_jwt_required
    def post(self, name):
        if ItemModel.find_by_name(name):
            return {'message': "An item with name '{}' already exists.".format(name)}, 400

        data = self.parser.parse_args()

        item = ItemModel(name, **data)

        try:
            item.save_to_db()
        except:
            return {"message": "An error occurred while inserting the item."}, 500

        return item.json(), 201

expired_token_loader
invalid_token_loader
重新定义TOKEN回调错误内容,还有更多的请参考Changing Default Behaviors

#过期令牌
@jwt.expired_token_loader
def expired_token_callback():
    return jsonify({
        'message': 'The token has expired.',
        'error': 'token_expired'
    }), 401
#无效令牌
@jwt.invalid_token_loader
def invalid_token_callback(error):  # we have to keep the argument here, since it's passed in by the caller internally
    return jsonify({
        'message': 'Signature verification failed.',
        'error': 'invalid_token'
    }), 401

最后我们来介绍黑名单系统
token_in_blacklist_loader by app.py

app.config['JWT_BLACKLIST_ENABLED'] = True  # enable blacklist feature
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = ['access', 'refresh']  # allow blacklisting for access and refresh tokens
# 检查此令牌是否属于黑名单,并在启用黑名单时调用
@jwt.token_in_blacklist_loader
def check_if_token_in_blacklist(decrypted_token):
    return decrypted_token['jti'] in BLACKLIST

可以看到此拓展插件给我们的用户管理提供了更多的可能

回到目录

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容