【Flask】使用 Token 作为身份验证和会话管理

【Flask】使用 Token 作为身份验证和会话管理

在 Flask 中生成 token 通常用于身份验证和会话管理。最常用的方法是使用其扩展,如 Flask-JWT 或 Flask-Security。

假设我们已经写好了简单的登录注册接口:

python 复制代码
@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 来实现:

bash 复制代码
pip install Flask-JWT-Extended

修改 Flask 应用以集成 JWT:
1. 配置 Flask-JWT-Extended:

python 复制代码
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:

python 复制代码
@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() 装饰器。例如,如果您有一个需要用户登录才能访问的路由:

python 复制代码
@app.route('/protected')
@jwt_required()
def protected_route():
    current_user = get_jwt_identity()
    return jsonify(logged_in_as=current_user), 200
  1. 数据库设置:
    确保您的数据库模型 User 已经设置好并且包含了 usernamepassword 字段。这通常在 Flask 应用的模型定义部分完成,例如使用 Flask-SQLAlchemy。
python 复制代码
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}

示例代码

python 复制代码
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 模块来生成一个安全的秘钥,例如:

python 复制代码
import secrets
secret_key = secrets.token_urlsafe(64)
print(secret_key)

通常,最佳实践是将 JWT Secret Key 存储在环境变量中。这样,可以在不同的部署环境中使用不同的秘钥,而无需更改代码。例如,在 Flask 应用中,可以这样设置:

python 复制代码
import os
app.config['JWT_SECRET_KEY'] = os.environ.get('JWT_SECRET_KEY', 'your_default_secret_key')

这里,如果环境变量 JWT_SECRET_KEY 存在,则使用它;如果不存在,使用默认值 'your_default_secret_key'

相关推荐
1.01^10008 分钟前
[1111].集成开发工具Pycharm安装与使用
python·pycharm
HEX9CF9 分钟前
【Django】测试带有 CSRF 验证的 POST 表单 API 报错:Forbidden (CSRF cookie not set.)
python·django·csrf
会说法语的猪1 小时前
springboot实现图片上传、下载功能
java·spring boot·后端
凡人的AI工具箱1 小时前
每天40分玩转Django:实操多语言博客
人工智能·后端·python·django·sqlite
Py办公羊大侠1 小时前
Excel批量设置行高,Excel表格设置自动换行后打印显示不全,Excel表格设置最合适的行高后打印显示不全,完美解决方案!!!
python·excel·打印·openpyxl·自动换行·显示不全
PieroPc1 小时前
Python tkinter写的《电脑装配单》和 Html版 可打印 可导出 excel 文件
python·html·电脑
Cachel wood1 小时前
Django REST framework (DRF)中的api_view和APIView权限控制
javascript·vue.js·后端·python·ui·django·前端框架
m0_748234081 小时前
Spring Boot教程之三十一:入门 Web
前端·spring boot·后端
暮色尽染1 小时前
Python 正则表达式
开发语言·python
想成为高手4991 小时前
国产之光--仓颉编程语言的实战案例分析
后端