如何为Flask应用添加API密钥认证 - The Teclado博客

作者:API传播员 · 2025-12-17 · 阅读时间:4分钟

API密钥认证功能,并结合Flask RESTful相关库实现这一目标。


如何在数据库中生成和存储API密钥

创建“设备模型”

在实现API密钥认证之前,我们需要设计一个数据库模型来存储相关数据。使用SQLAlchemy时,第一步是创建一个模型来保存“非人类用户”(即设备)及其对应的API密钥信息。

我们将创建一个名为DeviceModel的模型,该模型包含以下字段:

  • id:唯一的自动递增标识符,用于内部标识。
  • device_name:描述设备的字符串。
  • device_key:设备的API密钥,用于向API端点发出请求。
  • user_id:与用户的一对多关系,用于标识设备所属的用户。

以下是DeviceModel的代码实现:

from db import db
import uuid

class DeviceModel(db.Model):
    __tablename__ = 'devices'    id = db.Column(db.Integer, primary_key=True)
    device_name = db.Column(db.String(80))
    device_key = db.Column(db.String(80))
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    user = db.relationship('UserModel', back_populates='devices')    def __init__(self, device_name, user_id, device_key=None):
        self.device_name = device_name
        self.user_id = user_id
        self.device_key = device_key or uuid.uuid4().hex    def json(self):
        return {
            'device_name': self.device_name,
            'device_key': self.device_key,
            'user_id': self.user_id
        }    @classmethod
    def find_by_name(cls, device_name):
        return cls.query.filter_by(device_name=device_name).first()    @classmethod
    def find_by_device_key(cls, device_key):
        return cls.query.filter_by(device_key=device_key).first()

此外,我们需要在用户模型中添加与设备模型的关系:

class UserModel(db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80))
    password = db.Column(db.String(80))
    devices = db.relationship('DeviceModel', back_populates='user')

API端点注册新设备和API密钥

为了让用户能够创建新设备并生成API密钥,我们需要添加一个Flask RESTful资源。以下是实现代码:

from flask_restful import Resource, reqparse
from flask_jwt import jwt_required, current_identity
from models.device import DeviceModel

class AddDevice(Resource):
    parser = reqparse.RequestParser()
    parser.add_argument('device_name', type=str, required=True, help="Device name cannot be blank.")    @jwt_required()
    def post(self):
        data = AddDevice.parser.parse_args()
        name = data['device_name']        if DeviceModel.find_by_name(name):
            return {'message': f"Device with name '{name}' already exists."}, 400        new_device = DeviceModel(device_name=name, user_id=current_identity.id)
        new_device.save_to_db()        return {'api_key': new_device.device_key}, 201

接着,我们需要在Flask应用中注册该资源,以生成相应的端点:

from resources.device import AddDevice

api.add_resource(AddDevice, '/user/add-device')

用户可以通过向/user/add-device端点发送POST请求来添加新设备。请求示例如下:

{
    "device_name": "example_device"
}

成功响应将返回生成的API密钥:

{
    "api_key": "ef229daa-d058-4dd4-9c93-24761842aec5"
}

如何在某些Flask端点中要求API密钥

在用户成功创建设备并API密钥访问的端点。以下是实现方法:

创建API密钥验证装饰器

我们可以在security.py中定义一个装饰器,用于验证API密钥的有效性:

from models.device import DeviceModel
from functools import wraps
from flask import request
from hmac import compare_digest

def api_key_required(func):
    @wraps(func)
    def decorator(*args, **kwargs):
        api_key = request.json.get('api_key')
        if not api_key or not is_valid(api_key):
            return {"message": "Invalid API key provided."}, 403
        return func(*args, **kwargs)    return decoratordef is_valid(api_key):
    device = DeviceModel.find_by_device_key(api_key)
    return device and compare_digest(device.device_key, api_key)

应用装饰器到端点

在需要API密钥验证的端点上,使用@api_key_required装饰器。例如:

from flask_restful import Resource
from security import api_key_required

class ProtectedResource(Resource):
    @api_key_required
    def post(self):
        return {"message": "Access granted."}, 200

用户在访问该端点时,需要在请求中包含API密钥,例如:

{
    "api_key": "ef229daa-d058-4dd4-9c93-24761842aec5"
}

总结

通过本文的讲解,您已经了解了如何为Flask应用程序添加API密钥认证功能。从创建数据库模型到实现API端点,再到验证API密钥,我们逐步完成了整个流程。这种认证方式适用于非人类用户的API访问场景,同时也为您的应用提供了更高的安全性。

希望本文对您有所帮助!如果您想进一步学习如何使用Flask和开发REST API,可以参考相关课程或文档。

原文链接: https://blog.teclado.com/api-key-authentication-with-flask/