更多擴展
https://www.jianshu.com/p/10d0da01244c
**概念理解:**
* 刷新令牌的過期時間設置的要比 token久
* 我們使用token來進行用戶是否登錄判斷, 當token過期后, 前端使用 刷新令牌, 來獲取新的token
**實現步驟**
* 當用戶登錄成功后,返回 token 和 refresh_token
* 前端將其保存起來(保存位置看情況而定)
* 在發送請求的時候攜帶上 token, 默認的是在 headers 的 Authorization, 可以自己設置(看下邊鏈接)這里我設置在json中獲取
* 后台判斷是否符合要求,是否過期, 一般由自帶裝飾器完成
* 假如過期,前端,攜帶 refresh_token 默認的是在 Authorization, 可以自己設置(看下邊鏈接) 去后台獲取新的token,然后保存,再次請求
后端實現:
from flask import Flask, request, jsonify, render_template from flask_jwt_extended import ( JWTManager, jwt_required, create_access_token, jwt_refresh_token_required, create_refresh_token, get_jwt_identity ) import config app = Flask(__name__) app.config["JWT_ACCESS_TOKEN_EXPIRES"] = 5 app.config['JWT_SECRET_KEY'] = 'super-secret' # Change this! app.config["JWT_TOKEN_LOCATION"] = ['json'] # 設置從前端請求的json數據 中獲取 token 默認是在Authorization
app.confg["JWT_JSON_KEY"] = "token" # 設置 從json中的 token字段獲取,token, # app.config["JWT_REFRESH_JSON_KEY"] = "token" app.config.from_object(config) jwt = JWTManager(app) @app.route("/index", methods=["GET"]) def index(): return render_template("login.html") @app.route('/login', methods=['POST']) def login(): # if request.method == "GET": # return render_template("login.html") # else: username = request.form.get('username', None) password = request.form.get('password', None) if username != 'test' or password != 'test': return jsonify({"msg": "Bad username or password"}), 401 # Use create_access_token() and create_refresh_token() to create our # access and refresh tokens ret = { 'access_token': create_access_token(identity={"username": "liuyong", "age": "24"}), 'refresh_token': create_refresh_token(identity={"username": "liuyong", "age": "25"}) } return jsonify(ret), 200 # The jwt_refresh_token_required decorator insures a valid refresh # token is present in the request before calling this endpoint. We # can use the get_jwt_identity() function to get the identity of # the refresh token, and use the create_access_token() function again @app.route("/test", methods=["POST"]) @jwt_required def test(): a = get_jwt_identity() print(a.get("username")) print(a) return jsonify({"tets": "test"}) # to make a new access token for this identity. @app.route('/refresh', methods=['POST']) @jwt_refresh_token_required def refresh(): current_user = get_jwt_identity() ret = { 'access_token': create_access_token(identity=current_user) } return jsonify(ret), 200 @app.route('/protected', methods=['GET']) @jwt_required def protected(): username = get_jwt_identity() return jsonify(logged_in_as=username), 200 if __name__ == '__main__': app.run()
前端代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>登錄</title> <!-- <link rel="stylesheet" href="js/jquery-3.5.1.min.js"> --> <link rel="stylesheet" href="static/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="static/css/style.css"> </head> <body> <div class="row"> <div class="login-div col-xs-12 col-sm-2 col-sm-offset-5"> <div class="form-group first"> <label for="exampleInputEmail1">用戶名</label> <input type="username" name="username" class="form-control username" id="exampleInputuserName1" placeholder="用戶名"> </div> <div class="form-group"> <label for="exampleInputPassword1">密碼</label> <input type="password" name="password" class="form-control password" id="exampleInputPassword1" placeholder="Password"> </div> <div class="login-btn"> <button type="button" class="btn btn-info">登錄</button> </div> <hr/> <div class="footer" > <p> 還沒有賬戶~ <a class="register">注冊</a> </p> </div> </div> </div> <script src="static/js/jquery-3.5.1.min.js"></script> <script> $(".btn").click(function(){ var username = $(".username").val(); var password = $(".password").val(); $.ajax({ url: "/login", type: "POST", data: {"username": username, "password": password}, success: function(data){ sessionStorage.setItem("token", data.access_token), sessionStorage.setItem("refree_token", data.refresh_token), console.log(data), console.log(sessionStorage.getItem("token")) console.log(sessionStorage.se) // window.location.href = "/test" } }) }); $(".register").click(function(){ # 這里 攜帶token 向 test 發送post請求 var data = {"token": sessionStorage.getItem("token")} $.ajax({ url: "/test", type: "POST", dataType:"json", contentType:"application/json", data: JSON.stringify(data), success: function(data){ console.log(data) }, error: function(zhr){ # 這里未作其他判斷, 只是當失敗的時候(在測試用一般為token過期),使用 refresh_token 從后台獲取新的token var haha ={"token": sessionStorage.getItem("token"), "refresh_token": sessionStorage.getItem("refree_token")}; $.ajax({ url: "/refresh", type: "post", contentType:"application/json", data: JSON.stringify(haha), # 因為之前設置了從json中獲取,所以務必保證,前端向后台發送的數據為 json數據,否則會獲取不到 success: function(data){ sessionStorage.setItem("token", data.access_token) # 重新設置到session中 } }) } }) }); </script> </body> </html>
下邊這兩個仔細看下也就明白了
https://flask-jwt-extended.readthedocs.io/en/latest/refresh_tokens/
https://flask-jwt-extended.readthedocs.io/en/stable/options/