【Flask】使用 Token 作为身份验证和会话管理
在 Flask 中生成 token 通常用于身份验证和会话管理。最常用的方法是使用其扩展,如 Flask-JWT 或 Flask-Security。
假设我们已经写好了简单的登录注册接口:
@app.route('/api/register', methods=['POST']) def register(): data = request.get_json() # 确认数据有效性 username = data.get('username') password = data.get('password') if not username or not password: return jsonify({'message': 'Missing username or password'}), 400 # 检查用户名是否已存在 if User.query.filter_by(username=username).first(): return jsonify({'message': 'Username already exists'}), 400 # 创建新用户 hashed_password = generate_password_hash(password) new_user = User(username=username, password=hashed_password) db.session.add(new_user) db.session.commit() return jsonify({'message': 'User created successfully', 'user': new_user.to_dict()}), 201 @app.route('/api/login', methods=['POST']) def login(): data = request.get_json() username = data.get('username') password = data.get('password') if not username or not password: return jsonify({'message': 'Missing username or password'}), 400 # 检查用户是否存在 user = User.query.filter_by(username=username).first() if user and check_password_hash(user.password, password): # 在这里,你应该生成并返回一个认证令牌 return jsonify({'message': 'Login successful', 'user': user.to_dict()}), 200 else: return jsonify({'message': 'Invalid credentials'}), 401 if __name__ == '__main__': app.run(debug=True)
为了添加 token,首先,需要一个方式来生成和验证 JWT(JSON Web Tokens)。通过安装 Flask-JWT-Extended 来实现:
pip install Flask-JWT-Extended
修改 Flask 应用以集成 JWT:
1. 配置 Flask-JWT-Extended:
from flask import Flask, jsonify, request from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity from werkzeug.security import generate_password_hash, check_password_hash # 其他必要的导入 app = Flask(__name__) app.config['JWT_SECRET_KEY'] = 'your_jwt_secret_key' # 使用一个安全的密钥 jwt = JWTManager(app)
2. 生成 Token:
@app.route('/api/login', methods=['POST']) def login(): # 现有代码... if user and check_password_hash(user.password, password): access_token = create_access_token(identity=username) return jsonify({'message': 'Login successful', 'access_token': access_token, 'user': user.to_dict()}), 200 else: return jsonify({'message': 'Invalid credentials'}), 401
在这里,create_access_token 函数用于生成 JWT。identity 参数通常是用户的唯一标识(如用户名)。
3. 保护路由:
对于需要认证的路由,使用 @jwt_required() 装饰器。例如,如果您有一个需要用户登录才能访问的路由:
@app.route('/protected') @jwt_required() def protected_route(): current_user = get_jwt_identity() return jsonify(logged_in_as=current_user), 200
- 数据库设置:
确保您的数据库模型 User 已经设置好并且包含了 username 和 password 字段。这通常在 Flask 应用的模型定义部分完成,例如使用 Flask-SQLAlchemy。
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy(app) class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(50), unique=True, nullable=False) password = db.Column(db.String(80), nullable=False) # 可选:将用户对象转换为字典形式 def to_dict(self): return {"id": self.id, "username": self.username}
示例代码
from flask import Flask, jsonify, request from flask_sqlalchemy import SQLAlchemy from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity from werkzeug.security import generate_password_hash, check_password_hash # 应用和数据库配置 app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db' # 使用 SQLite 数据库 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['JWT_SECRET_KEY'] = 'your_jwt_secret_key' # JWT 秘钥 db = SQLAlchemy(app) jwt = JWTManager(app) # 用户模型 class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(50), unique=True, nullable=False) password = db.Column(db.String(80), nullable=False) # 创建数据库 @app.before_first_request def create_tables(): db.create_all() # 注册接口 @app.route('/register', methods=['POST']) def register(): data = request.get_json() username = data.get('username') password = data.get('password') if not username or not password: return jsonify({'message': 'Missing username or password'}), 400 if User.query.filter_by(username=username).first(): return jsonify({'message': 'Username already exists'}), 400 hashed_password = generate_password_hash(password) new_user = User(username=username, password=hashed_password) db.session.add(new_user) db.session.commit() return jsonify({'message': 'User created successfully'}), 201 # 登录接口 @app.route('/login', methods=['POST']) def login(): data = request.get_json() username = data.get('username') password = data.get('password') if not username or not password: return jsonify({'message': 'Missing username or password'}), 400 user = User.query.filter_by(username=username).first() if user and check_password_hash(user.password, password): access_token = create_access_token(identity=username) return jsonify({'message': 'Login successful', 'access_token': access_token}), 200 else: return jsonify({'message': 'Invalid credentials'}), 401 # 受保护的路由 @app.route('/protected', methods=['GET']) @jwt_required() def protected(): current_user = get_jwt_identity() return jsonify({'logged_in_as': current_user}), 200 if __name__ == '__main__': app.run(debug=True)
如何获取secret_key
加密 token 的秘钥(通常称为 “JWT Secret Key”)是自己定义的一个字符串。这个秘钥用于加密和解密 JSON Web Tokens(JWT),因此保持其安全性非常重要。秘钥应该足够复杂,以防止猜测或暴力破解攻击。
秘钥应该是一个长且随机的字符串。可以使用 Python 的 secrets 模块来生成一个安全的秘钥,例如:
import secrets secret_key = secrets.token_urlsafe(64) print(secret_key)
通常,最佳实践是将 JWT Secret Key 存储在环境变量中。这样,可以在不同的部署环境中使用不同的秘钥,而无需更改代码。例如,在 Flask 应用中,可以这样设置:
import os app.config['JWT_SECRET_KEY'] = os.environ.get('JWT_SECRET_KEY', 'your_default_secret_key')
这里,如果环境变量 JWT_SECRET_KEY 存在,则使用它;如果不存在,使用默认值 ‘your_default_secret_key’。