Flask JWT Extended 的令牌和刷新令牌
更多扩展
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/