第五章 來自復(fù)雜對象的Token

一種非常常見的設(shè)置是將用戶信息(用戶名、密碼、角色等)存儲在數(shù)據(jù)庫中。現(xiàn)在,假設(shè)我們要創(chuàng)建一個訪問令牌,其中令牌標(biāo)識是用戶名,我們還希望將用戶角色作為附加聲明存儲在令牌中。我們可以使用上一節(jié)討論的user_claims_loader()裝飾器來實現(xiàn)這一點。

  但是,如果我們將用戶名傳遞給`user_claims_loader()`,我們最終需要從數(shù)據(jù)庫查詢該用戶兩次。
  * 1 第一次是當(dāng)?shù)卿浂它c被點擊時,我們需要驗證用戶名和密碼。
  * 2 第二次是在`user_claims_loader()`函數(shù)中,因為我們需要查詢這個用戶的角色。這不是什么大事,但顯然它可以更有效率。

在本章的方法中,提供了將任何對象傳遞給create_access_token()函數(shù)的能力,然后將該函數(shù)作為user_claims_loader()傳遞。這允許我們只訪問數(shù)據(jù)庫一次,但是引入了一個需要解決的新問題。我們?nèi)匀恍枰獜膶ο笾刑崛∮脩裘?,這樣我們就可以讓用戶名作為新令牌的標(biāo)識。我們可以為此使用第二個裝飾器user_identity_loader(),它允許您接收傳入create_access_token()的任何對象,并從該對象返回一個json序列化的標(biāo)識。
請看示例代碼:

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)

#創(chuàng)建一個用來構(gòu)建JWT數(shù)據(jù)的復(fù)雜對象
#看起來有點像SQLAlchemy 的實例
class UserObject:
    def __init__(self, username, roles):
        self.username = username
        self.roles = roles

#定義jwt.user_claims_loader裝飾器,該裝飾器會在調(diào)用create_access_token函數(shù)時自動被調(diào)用,
#user_claims_loader的參數(shù)就是傳遞給 create_access_token的參數(shù)
#user_claims_loader返回的數(shù)據(jù)會被保存到j(luò)wt 中,作為claims存在
@jwt.user_claims_loader
def add_claims_to_access_token(user):
    return {'roles': user.roles}

#user_identity_loader裝飾器,該裝飾器會在調(diào)用create_access_token函數(shù)時自動被調(diào)用,
#user_identity_loader的參數(shù)就是傳遞給 create_access_token的參數(shù)
#user_claims_loader返回的數(shù)據(jù)會被保存到j(luò)wt 中,作為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()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容