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/

原文地址:https://www.cnblogs.com/ShanCe/p/13971710.html