美文网首页flask-jwt-extend 文档中文版
第五章 来自复杂对象的Token

第五章 来自复杂对象的Token

作者: suenism | 来源:发表于2020-02-16 13:31 被阅读0次

    一种非常常见的设置是将用户信息(用户名、密码、角色等)存储在数据库中。现在,假设我们要创建一个访问令牌,其中令牌标识是用户名,我们还希望将用户角色作为附加声明存储在令牌中。我们可以使用上一节讨论的user_claims_loader()装饰器来实现这一点。

      但是,如果我们将用户名传递给`user_claims_loader()`,我们最终需要从数据库查询该用户两次。
      * 1 第一次是当登录端点被点击时,我们需要验证用户名和密码。
      * 2 第二次是在`user_claims_loader()`函数中,因为我们需要查询这个用户的角色。这不是什么大事,但显然它可以更有效率。
    

    在本章的方法中,提供了将任何对象传递给create_access_token()函数的能力,然后将该函数作为user_claims_loader()传递。这允许我们只访问数据库一次,但是引入了一个需要解决的新问题。我们仍然需要从对象中提取用户名,这样我们就可以让用户名作为新令牌的标识。我们可以为此使用第二个装饰器user_identity_loader(),它允许您接收传入create_access_token()的任何对象,并从该对象返回一个json序列化的标识。
    请看示例代码:

    from flask import Flask, jsonify, request
    from flask_jwt_extended import (
        JWTManager, jwt_required, create_access_token,
        get_jwt_identity, get_jwt_claims
    )
    
    app = Flask(__name__)
    
    app.config['JWT_SECRET_KEY'] = 'super-secret'  # Change this!
    jwt = JWTManager(app)
    
    #创建一个用来构建JWT数据的复杂对象
    #看起来有点像SQLAlchemy 的实例
    class UserObject:
        def __init__(self, username, roles):
            self.username = username
            self.roles = roles
    
    #定义jwt.user_claims_loader装饰器,该装饰器会在调用create_access_token函数时自动被调用,
    #user_claims_loader的参数就是传递给 create_access_token的参数
    #user_claims_loader返回的数据会被保存到jwt 中,作为claims存在
    @jwt.user_claims_loader
    def add_claims_to_access_token(user):
        return {'roles': user.roles}
    
    #user_identity_loader装饰器,该装饰器会在调用create_access_token函数时自动被调用,
    #user_identity_loader的参数就是传递给 create_access_token的参数
    #user_claims_loader返回的数据会被保存到jwt 中,作为identity存在
    @jwt.user_identity_loader
    def user_identity_lookup(user):
        return user.username
    
    
    @app.route('/login', methods=['POST'])
    def login():
        username = request.json.get('username', None)
        password = request.json.get('password', None)
        if username != 'test' or password != 'test':
            return jsonify({"msg": "Bad username or password"}), 401
    
        # Create an example UserObject
        user = UserObject(username='test', roles=['foo', 'bar'])
    
        # We can now pass this complex object directly to the
        # create_access_token method. This will allow us to access
        # the properties of this object in the user_claims_loader
        # function, and get the identity of this object from the
        # user_identity_loader function.
        access_token = create_access_token(identity=user)
        ret = {'access_token': access_token}
        return jsonify(ret), 200
    
    
    @app.route('/protected', methods=['GET'])
    @jwt_required
    def protected():
        ret = {
            'current_identity': get_jwt_identity(),  # test
            'current_roles': get_jwt_claims()['roles']  # ['foo', 'bar']
        }
        return jsonify(ret), 200
    
    
    if __name__ == '__main__':
        app.run()
    

    相关文章

      网友评论

        本文标题:第五章 来自复杂对象的Token

        本文链接:https://www.haomeiwen.com/subject/iyppfhtx.html