FastAPI,如其名所示,是一个极为高效的框架,特别适用于构建 API 后端服务。而在与其他网站的 API 接口进行交互时,API Key认证是一种非常普遍的安全机制。典型的例子是ChatGPT的接口,我们需要申请一个专属的API Key才能发起有效的请求。
虽然我们可以直接在定义接口时自定义接收参数,但这种方式需要在每个接口都增加相同的代码,十分不优雅,且该方式不支持FastAPI自带的swagger文档友好显示。
本文将介绍在FastAPI框架中如何为我们的后端服务添加API Key认证,且使用两种不同的方案实现:一种是将 API Key 放在 URL 请求路径中,另一种是将 API Key 放在请求头(Header)中。
import uvicorn
from fastapi import HTTPException, status, Security, FastAPI
from fastapi.security import APIKeyQuery
# 可用的API_KEYS列表
API_KEYS = ["9d207bf0-10f5-4d8f-a479-22ff5aeff8d1", ...]
# 创建一个用于解析路径传参的对象
api_key_query = APIKeyQuery(name="api-key", auto_error=False)
# 定义一个获取请求中的api-key的函数 该函数接收一个上一步创建的对象封装
def get_api_key(api_key: str = Security(api_key_query)) -> str:
if api_key in API_KEYS:
return api_key
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid or missing API Key")
app = FastAPI()
@app.get("/public")
def public():
"""一个公共接口 无需api-key即可访问"""
return "Public Endpoint."
# 需要api-key的接口,注意接受参数的写法。
@app.get("/private")
def private(api_key: str = Security(get_api_key)):
"""一个私有端点 需要在请求url中传入api-key"""
return f"Private Endpoint. API Key: {api_key}"
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
启动应用后,可以使用如下请求来访问“私有端点”:
GET http://localhost:8000/private?api-key=9d207bf0-10f5-4d8f-a479-22ff5aeff8d1
访问接口文档,可以看到有很好的支持。
点击Authorize
按钮,填入api-key,这样调用需要认证的接口时就可以自动带上api-key了。
这种方式相对前一种方式会更安全一些,推荐。
"""为请求添加api-key的示例 api-key通过header的方式发送"""
import uvicorn
from fastapi import HTTPException, status, Security, FastAPI
from fastapi.security import APIKeyHeader
# 可用的API_KEYS列表
API_KEYS = ["9d207bf0-10f5-4d8f-a479-22ff5aeff8d1", ...]
# 创建一个用于解析路径传参的对象
api_key_header = APIKeyHeader(name="api-key", auto_error=False)
# 定义一个获取请求中的api-key的函数 该函数接收一个上一步创建的对象封装
def get_api_key(api_key: str = Security(api_key_header)) -> str:
if api_key in API_KEYS:
return api_key
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid or missing API Key")
app = FastAPI()
@app.get("/public")
def public():
"""一个公共接口 无需api-key即可访问"""
return "Public Endpoint."
# 需要api-key的接口,注意接受参数的写法。
@app.get("/private")
def private(api_key: str = Security(get_api_key)):
"""一个私有端点 需要在请求url中传入api-key"""
return f"Private Endpoint. API Key: {api_key}"
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
启动应用后,你可以使用如下 curl 命令来访问“私有端点”:
curl -H "api-key: 9d207bf0-10f5-4d8f-a479-22ff5aeff8d1" http://localhost:8000/private
配置完成,一切正常!
(完)