FastAPI 核心安全功能与模板渲染的完整示:登录、CSRF、JWT、会话、认证和缓存功能
以下是一个整合 FastAPI 核心安全功能与模板渲染的完整示例,基于多个技术文档的最佳实践,包含登录、CSRF、JWT、会话、认证和缓存功能:
from datetime import datetime, timedelta
from fastapi import FastAPI, Request, Depends, HTTPException, Form
from fastapi.templating import Jinja2Templates
from fastapi.security import OAuth2PasswordBearer
from fastapi_csrf_protect import CsrfProtect
from fastapi_sessions import SessionManager
from fastapi_sessions.backends.redis import RedisBackend
from jose import jwt
from passlib.context import CryptContext
import aioredis
import os
# ===== 基础配置 =====
app = FastAPI()
templates = Jinja2Templates(directory="templates")
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/login")
# ===== 安全配置 =====
JWT_SECRET = os.getenv("SECRET_KEY", "your_secure_key_123")
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE = timedelta(minutes=30)
# ===== Redis连接 =====
redis = aioredis.from_url("redis://localhost:6379")
session_backend = RedisBackend(redis, prefix="session:", ttl=3600)
session_manager = SessionManager(session_backend)
# ===== CSRF保护 =====
@CsrfProtect.load_config
def get_csrf_config():
return {"secret_key": JWT_SECRET}
# ===== 用户模型 =====
class User:
def __init__(self, username: str, password: str):
self.username = username
self.hashed_password = pwd_context.hash(password)
# 模拟数据库
fake_users_db = {
"admin": User("admin", "secret123")
}
# ===== 核心功能实现 =====
def create_jwt(username: str) -> str:
payload = {
"sub": username,
"exp": datetime.utcnow() + ACCESS_TOKEN_EXPIRE,
"csrf": CsrfProtect.generate_csrf()
}
return jwt.encode(payload, JWT_SECRET, ALGORITHM)
async def get_current_user(
request: Request,
token: str = Depends(oauth2_scheme),
csrf_protect: CsrfProtect = Depends()
):
try:
# 验证CSRF令牌
await csrf_protect.validate_csrf(request)
payload = jwt.decode(token, JWT_SECRET, algorithms=[ALGORITHM])
username = payload.get("sub")
if user := fake_users_db.get(username):
return user
except Exception:
raise HTTPException(401, "Invalid credentials")
# ===== 路由定义 =====
@app.get("/")
async def login_page(request: Request):
return templates.TemplateResponse("login.html", {
"request": request,
"csrf_token": CsrfProtect.generate_csrf()
})
@app.post("/login")
async def login(
request: Request,
username: str = Form(...),
password: str = Form(...),
csrf_protect: CsrfProtect = Depends()
):
# CSRF验证
await csrf_protect.validate_csrf(request)
user = fake_users_db.get(username)
if not user or not pwd_context.verify(password, user.hashed_password):
return templates.TemplateResponse("login.html", {
"request": request,
"error": "Invalid credentials"
})
# 创建会话和JWT
session_id = session_manager.create_session(username)
response = templates.TemplateResponse("dashboard.html", {
"request": request,
"user": username
})
# 设置Cookie
response.set_cookie("session_id", session_id, httponly=True)
response.set_cookie("access_token", create_jwt(username))
return response
@app.get("/dashboard")
async def dashboard(
request: Request,
user: User = Depends(get_current_user)
):
return templates.TemplateResponse("dashboard.html", {
"request": request,
"user": user.username
})
# ===== 缓存实现 =====
from fastapi_cache import FastAPICache
from fastapi_cache.backends.redis import RedisBackend
from fastapi_cache.decorator import cache
FastAPICache.init(RedisBackend(redis), prefix="fastapi-cache")
@app.get("/profile")
@cache(expire=300)
async def user_profile(user: User = Depends(get_current_user)):
return {"username": user.username, "cached_at": datetime.now()}
# ===== 模板文件 =====
"""
<!-- templates/login.html -->
<html>
<head><title>Login</title></head>
<body>
{% if error %}<p style="color:red">{{ error }}</p>{% endif %}
<form method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input name="username" placeholder="Username">
<input type="password" name="password" placeholder="Password">
<button type="submit">Login</button>
</form>
</body>
</html>
<!-- templates/dashboard.html -->
<html>
<head><title>Dashboard</title></head>
<body>
<h1>Welcome {{ user }}!</h1>
<p>Session ID: {{ request.cookies.session_id }}</p>
</body>
</html>
"""
功能说明 (整合多个技术文档)
-
安全认证体系
• CSRF保护:使用fastapi-csrf-protect
中间件,在登录表单中通过隐藏字段传递令牌
• JWT认证:令牌包含用户身份和CSRF令牌双重验证,自动刷新机制
• 会话管理:Redis存储会话数据,支持多设备登录追踪 -
模板交互设计
• 登录页自动注入CSRF令牌到表单
• 错误消息动态渲染(如无效凭证提示)
• 仪表盘展示会话信息和缓存时间 -
缓存优化策略
• Redis缓存用户配置数据,减少数据库查询
• 自动过期机制保证数据新鲜度
• 支持条件缓存(根据用户角色差异化) -
防御机制
• 密码使用bcrypt算法加密存储
• HTTP-only Cookie存储会话ID
• 双重验证机制(JWT+Session)
部署建议
# 安装依赖
pip install fastapi[all] fastapi-csrf-protect fastapi-sessions python-jose[cryptography] aioredis
# 运行服务
uvicorn main:app --reload --ws-ping-interval 30
该实现综合了以下技术文档的关键点:
• JWT生成与验证流程参考网页1和网页4
• 会话管理采用网页3的Redis存储方案
• 模板交互设计结合网页5和网页7的渲染技术
• 安全策略整合网页2的中间件配置建议
可通过访问 /docs
查看自动生成的API文档,或直接通过浏览器测试登录流程。生产环境建议补充HTTPS配置和密钥轮换机制。