🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
大多数使用 JWT 的项目其实都是使用的 JWS(JSON Web Signature), JWT 并不等于 JWS,JWS 只是JWT的一种实现,除了 JWS 外,JWE(JSON Web Encryption) 也是JWT的一种实现。 一般我们使用 JWS 完全满足我们的需求。 安装依赖 ``` (.venv) root@airvip:~/python_app/flask-demo# pip install flask-jwt-extended ``` 常用配置 * `JWT_REFRESH_TOKEN_EXPIRES` 刷新 token 过期时间,默认 30 天。 * `JWT_ACCESS_TOKEN_EXPIRES` token 过期时间,默认 15 分钟 * `JWT_SECRET_KEY` 基于对称的签名算法所需的密钥,如 : `HS*`。如果没有设置,则使用 flask 的 `SECRET_KEY`值。 修改配置文件 `config.py` ``` class Config(object): SECRET_KEY = "AIRVip123456airvip" # 数据库、cache 配置省略 # JWT JWT_ACCESS_TOKEN_EXPIRES = 7200 ``` 对 `app` 目录下的 ` __init__` 初始化文件进行如下改造,添加 `jwt` 模块 ``` #!/usr/bin/env python3 # -*- encoding: utf-8 -*- from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_caching import Cache from flask_jwt_extended import JWTManager import logging from logging.handlers import RotatingFileHandler from config import config_map from app.utils.commons import ReCoverter db = SQLAlchemy() cache = Cache() # 创建 jwt 对象 jwt = JWTManager() logging.basicConfig(level=logging.ERROR) file_log_handler = RotatingFileHandler("logs/log", maxBytes=1024, backupCount=10) formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s') file_log_handler.setFormatter(formatter) logging.getLogger().addHandler(file_log_handler) def create_app(config_name): app = Flask(__name__) config_class = config_map[config_name] app.config.from_object(config_class) db.init_app(app) cache.init_app(app) # 使用 app 初始化 jwt jwt.init_app(app) app.url_map.converters["re"] = ReCoverter from app import api_1_0 app.register_blueprint(api_1_0.bp, url_prefix="/api/v1.0") from app import html app.register_blueprint(html.html) return app ``` 对 `app/api_1_0/controller` 下的 `passport.py` 控制器进行如下改造 ``` #!/usr/bin/env python3 # -*- encoding: utf-8 -*- from app.api_1_0 import bp from app import cache from flask import request,jsonify from flask_jwt_extended import ( create_access_token, create_refresh_token, jwt_refresh_token_required, jwt_required, get_jwt_identity ) @bp.route('/login', methods=['POST']) def login(): username = request.get_json()['username'] # 验证自己做 ret = { "access_token": create_access_token(identity=username), "refresh_token": create_refresh_token(identity=username) } return jsonify(ret) @bp.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) @bp.route('/protected', methods=['GET']) @jwt_required def protected(): username = get_jwt_identity() return jsonify(username=username) ``` **测试** ``` root@airvip:~# curl 127.0.0.1:5000/api/v1.0/login -X POST -H 'Content-Type: application/json' -d '{"username":"airvip"}' { "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MTA0MjA4ODUsIm5iZiI6MTYxMDQyMDg4NSwianRpIjoiZjQwOGY0YWYtMTllMi00NzU1LWE4NWQtNzMxOTdlNzg1YjMxIiwiZXhwIjoxNjEwNDI4MDg1LCJpZGVudGl0eSI6ImFpcnZpcCIsImZyZXNoIjpmYWxzZSwidHlwZSI6ImFjY2VzcyJ9.vmgt9EMqJjP17XQ7Sxcc1fU5FIsNzrKEvCPqZLBwCgM", "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MTA0MjA4ODUsIm5iZiI6MTYxMDQyMDg4NSwianRpIjoiNDk2YjgyMjItYTI3My00MGNhLWJlMmMtMTZkMWQ1MDU5YzY5IiwiZXhwIjoxNjEzMDEyODg1LCJpZGVudGl0eSI6ImFpcnZpcCIsInR5cGUiOiJyZWZyZXNoIn0.JiSlX81RR4QctrYq4jdThEIYGEIWHbgZi94Ra09U7c8" } # 刷新 token ,发送 http 请求的 header 用的是登录返回的 refresh_token root@airvip:~# curl 127.0.0.1:5000/api/v1.0/refresh -X POST -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MTA0MjA4ODUsIm5iZiI6MTYxMDQyMDg4NSwianRpIjoiNDk2YjgyMjItYTI3My00MGNhLWJlMmMtMTZkMWQ1MDU5YzY5IiwiZXhwIjoxNjEzMDEyODg1LCJpZGVudGl0eSI6ImFpcnZpcCIsInR5cGUiOiJyZWZyZXNoIn0.JiSlX81RR4QctrYq4jdThEIYGEIWHbgZi94Ra09U7c8' { "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MTA0MjA5MTAsIm5iZiI6MTYxMDQyMDkxMCwianRpIjoiN2Q5ZDBhOWYtZjc1OC00NzBmLThlNjUtZDQyMjk2YTgxZTRhIiwiZXhwIjoxNjEwNDI4MTEwLCJpZGVudGl0eSI6ImFpcnZpcCIsImZyZXNoIjpmYWxzZSwidHlwZSI6ImFjY2VzcyJ9.xj71pS97iXEVR68BPy1H8pKs82bITnqhOdLbHjlIr3w" } # 之后需要验证的方法,发送 http 请求的 header 用 access_token root@airvip:~# curl 127.0.0.1:5000/api/v1.0/protected -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MTA0MjA5MTAsIm5iZiI6MTYxMDQyMDkxMCwianRpIjoiN2Q5ZDBhOWYtZjc1OC00NzBmLThlNjUtZDQyMjk2YTgxZTRhIiwiZXhwIjoxNjEwNDI4MTEwLCJpZGVudGl0eSI6ImFpcnZpcCIsImZyZXNoIjpmYWxzZSwidHlwZSI6ImFjY2VzcyJ9.xj71pS97iXEVR68BPy1H8pKs82bITnqhOdLbHjlIr3w' { "username": "airvip" } root@airvip:~# ``` ![jwt 测试](https://img.kancloud.cn/18/f4/18f40c0d819252a5b648eec2fee86bff_1051x337.png) 传送门:[Flask-JWT-Extended’s 更多使用技巧](https://flask-jwt-extended.readthedocs.io/en/latest/)