fastapi:给管理后台增加http basic登录验证
一,代码
说明:只针对admin管理后台,不影响其他子应用如api
basic的代码
# app/core/adminbasic.py
import secrets
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
# 初始化 Basic 认证组件
security = HTTPBasic()
def verify_admin_user(credentials: HTTPBasicCredentials = Depends(security)):
"""校验管理后台的账号密码"""
correct_username = b"admin"
correct_password = b"secret_password_123"
# 使用 secrets.compare_digest 防止时序攻击
is_correct_username = secrets.compare_digest(
credentials.username.encode("utf-8"), correct_username
)
is_correct_password = secrets.compare_digest(
credentials.password.encode("utf-8"), correct_password
)
if not (is_correct_username and is_correct_password):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="账号或密码错误",
headers={"WWW-Authenticate": "Basic"},
)
return credentials.username
注入到app
# app/admin/main.py
from fastapi import FastAPI, Depends
from app.admin.views import users
from app.core.adminbasic import verify_admin_user
from app.core.exceptions import register_exception_handlers
from fastapi.staticfiles import StaticFiles
from app.core.redislink import lifespan
# 创建FastAPI应用,并传入 lifespan
# 创建独立隔离的管理后台子应用
admin_app = FastAPI(
title="管理后台系统",
dependencies=[Depends(verify_admin_user)] # 👈 核心:作为子应用全局依赖
)
# 注册全局异常捕获
register_exception_handlers(admin_app)
# 1. 挂载静态文件目录
# path="/static" 是浏览器访问静态文件的 URL 前缀
# directory="app/static" 是本地项目中的文件夹名称
# name="static" 是在 Jinja2 模板中引用时使用的别名
admin_app.mount("/static", StaticFiles(directory="app/static"), name="static")
# 注册路由模块
@admin_app.get("/")
def admin_home():
return {"message": "欢迎来到管理后台首页"}
admin_app.include_router(users.router)
注意对异常处理代码,要返回相应的headers信息,否则会导致登录窗口不弹出:
# 3. 捕获 HTTP 异常 (如: FastAPI 自带的 404, 403)
@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request: Request, exc: StarletteHTTPException):
print("http_exception_handler:", exc.status_code)
content = BaseResponse(code=exc.status_code, msg=exc.detail, data=None).model_dump()
# 👈 核心修改:如果 exc 里面有 headers(比如 Basic 认证的 WWW-Authenticate),就透传它
headers = getattr(exc, "headers", None) or {}
return JSONResponse(
status_code=exc.status_code,
content=content,
headers=headers # 👈 将 headers 塞回响应中
)
二,测试效果:

浙公网安备 33010602011771号