如何使用API密钥实现API认证 | 作者:Jaz Allibhai

作者:API传播员 · 2025-10-31 · 阅读时间:5分钟

所以您刚刚完成了构建一个 API,并希望确保只有授权用户能够访问它。为此,您为用户生成了 API 密钥。当用户向 API 的某个端点发出请求时,他们需要将 API 密钥与请求一起发送。接下来,您需要验证这些密钥的有效性,以确保只有合法用户能够访问您的 API。

本文将详细介绍如何实现 API 身份验证的工作原理,并提供具体的实现方法。


实现 API 身份验证时如何存储 API 密钥

与密码类似,API 密钥不应直接存储在数据库中。直接存储 API 密钥是一种不安全的做法,可能会导致数据泄露。在存储之前,应该对 API 密钥进行哈希或加密处理。这种方式可以确保即使数据库被恶意访问,密钥也无法直接被使用。

加密和哈希是两种将数据转换为不同字符序列的安全方法。例如,字符串 "Hello World" 经过加密或哈希后,可能会变成如下形式:364ac7cf699f309568d46d9d79d34c80fa9f6ec18d5f4f812e07dc4fg17aa65f


加密和哈希之间的区别

加密是可逆的,哈希是不可逆的

  • 加密:将字符串 "Hello World" 转换为一个随机字符串(如 364ac7cf69...),并且可以通过解密恢复原始字符串。
  • 哈希:一旦对字符串进行哈希运算,原始字符串将无法恢复。

为什么 API 身份验证需要同时使用加密和哈希

不同的应用场景对 API 密钥的存储和使用有不同的要求:

  • 仅使用哈希:例如,GitHub 在创建 API 密钥时只显示一次。如果用户丢失了密钥,则需要重新生成。此场景仅需要存储哈希版本的密钥。
  • 同时使用加密和哈希:例如,Twilio 允许用户在创建 API 密钥后再次查看密钥。这种情况下,应用需要存储密钥的加密版本(用于用户查看)和哈希版本(用于身份验证)。

如何使用哈希进行身份验证

以下是使用哈希进行 API 身份验证的步骤:

  1. 为用户生成一个新的 API 密钥。
  2. 对 API 密钥进行哈希处理,并将哈希值存储在数据库中。
  3. 用户在请求 API 时,需提供其 API 密钥。
  4. 验证步骤:
    • 对用户提供的 API 密钥进行哈希处理。
    • 在数据库中查找是否存在匹配的哈希值。
    • 如果匹配,表示请求有效;如果不匹配,则拒绝请求。

注意:为了安全性,建议用户将 API 密钥放在请求头中,而不是 URL 中。因为 URL 可能会被浏览器历史记录、缓存或服务器日志记录,而请求头通常不会被公开。


使用 Python 实现 API 密钥的生成、加密和哈希

以下是使用 Keycove 库实现 API 密钥生成、加密和哈希的示例。

安装 Keycove 库

pip install keycove

生成 API 密钥

from keycove import generate_token

api_key = generate_token()
print(api_key)
# 输出示例: 'rmQikHfXyJ_h92fHUiseNKd-f2deStO84o-t1QOkFuY'

对 API 密钥进行哈希处理

from keycove import hash

hashed_key = hash(value_to_hash=api_key)
print(hashed_key)
# 输出示例: '2ef7bde608ce5404e97d5f042f95f89f1c232871'

加密和解密 API 密钥

加密和解密需要一个密钥,该密钥应保持安全,不得公开。使用 generate_secret_key() 函数生成与加密和解密算法兼容的密钥。

加密 API 密钥

from keycove import encrypt, generate_secret_key

secret_key = generate_secret_key()
encrypted_key = encrypt(value_to_encrypt=api_key, secret_key=secret_key)
print(encrypted_key)
# 输出示例: 'gAAAAABgTD0yR3O4hV7Kb7PZ6N4iZA3uJNeL3_ZI2QmGJHbLZUj4Cy5B2Pgh4lX3JNLUZ4Q8OvJZ8OZyXUYd8l4XQJZIV64nJA=='

解密 API 密钥

from keycove import decrypt

decrypted_key = decrypt(encrypted_value=encrypted_key, secret_key=secret_key)
print(decrypted_key)
# 输出示例: 'rmQikHfXyJ_h92fHUiseNKd-f2deStO84o-t1QOkFuY'

使用 FastAPI 和 Keycove 实现完整的 API 身份验证

以下是一个完整的示例,展示如何使用 FastAPI 和 Keycove 实现 API 身份验证。

安装依赖

pip install fastapi "uvicorn[standard]" sqlalchemy keycove

启动服务器

uvicorn filename:app --reload

访问交互式文档:http://localhost:8000/docs

完整代码示例

from fastapi import FastAPI, Depends, HTTPException, status, Header
from sqlalchemy import create_engine, Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from keycove import encrypt, decrypt, hash, generate_token
from sqlalchemy.orm import Session

app = FastAPI()

SQLALCHEMY_DATABASE_URL = "sqlite:///db.sqlite3"
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

class Key(Base):
    __tablename__ = "keys"
    id = Column(Integer, primary_key=True, autoincrement=True)
    hashed_key = Column(String, nullable=False, unique=True)
    encrypted_key = Column(String, nullable=True)

Base.metadata.create_all(bind=engine)

secret_key = "EZdgwBIak481WZB8ZkZmzKHTDkRQFzDjeTrhSlU_v2g="

def verify_api_key(api_key: str = Header(None), db: Session = Depends(get_db)) -> None:
    key = db.query(Key).filter(Key.hashed_key == hash(api_key)).first()
    if not key:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="The provided API key is not valid."
        )

@app.get("/protected")
def protected_route(verify_api_key: None = Depends(verify_api_key)):
    return {"message": "Access granted"}

@app.post("/create_api_key")
def create_api_key(db: Session = Depends(get_db)):
    api_key = generate_token()
    hashed_key = hash(api_key)
    encrypted_key = encrypt(api_key, secret_key)
    new_key = Key(hashed_key=hashed_key, encrypted_key=encrypted_key)
    db.add(new_key)
    db.commit()
    db.refresh(new_key)
    return {"api_key": api_key}

@app.get("/decrypt_api_key")
def decrypt_api_key(api_key: str = Header(None), db: Session = Depends(get_db)):
    key = db.query(Key).filter(Key.hashed_key == hash(api_key)).first()
    return decrypt(key.encrypted_key, secret_key)

@app.get("/keys")
def get_keys(db: Session = Depends(get_db)):
    keys = db.query(Key).all()
    return {"keys": [key.hashed_key for key in keys]}

通过以上内容,您可以轻松实现一个安全的 API 身份验证系统。无论是生成、存储还是验证 API 密钥,都可以通过本文的方法确保数据的安全性。

原文链接: https://medium.com/@jaz1/how-api-authentication-works-4d735eeb6739