1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| from fastapi import Depends, FastAPI from fastapi.security import HTTPBasic, HTTPBasicCredentials
app = FastAPI() security = HTTPBasic()
@app.get("/users/me") async def read_current_user(credentials: HTTPBasicCredentials = Depends(security)): return {"username": credentials.username, "password": credentials.password} ``` - 核心组件: - `HTTPBasic`:创建基本认证的安全模式 - `HTTPBasicCredentials`:接收认证凭证的数据模型 - 流程说明: <pre class="mermaid">graph TD A[客户端请求] --> B{认证头是否存在?} B -->|否| C[返回401错误] B -->|是| D[解析Basic认证头] D --> E[返回凭证对象] E --> F[业务逻辑处理]</pre> - 自动处理: - 未携带认证头时自动返回401 Unauthorized错误 - 自动解析`Authorization: Basic <credentials>`头部信息
```python import secrets from fastapi import HTTPException, status
def verify_credentials(credentials: HTTPBasicCredentials): current_username_bytes = credentials.username.encode("utf8") correct_username_bytes = b"stanleyjobson" is_correct_username = secrets.compare_digest(current_username_bytes, correct_username_bytes) current_password_bytes = credentials.password.encode("utf8") correct_password_bytes = b"swordfish" is_correct_password = secrets.compare_digest(current_password_bytes, correct_password_bytes) 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.get("/secure/me") async def secure_endpoint(username: str = Depends(verify_credentials)): return {"username": username} ``` - 安全验证要点: - 使用`secrets.compare_digest`防止时序攻击 - 统一编码处理(UTF-8)确保特殊字符兼容性 - 自定义错误响应头保持WWW-Authenticate规范 - 优势: - 密码不再以明文形式出现在业务逻辑中 - 支持多层级依赖注入(可复用验证逻辑)
1. **HTTPS强制**: - 基本认证需配合HTTPS防止凭证泄露 - 通过中间件实现HTTP自动跳转HTTPS
2. **密码存储**: - 使用bcrypt或Argon2进行密码哈希存储 - 定期轮换服务器端密钥
3. **安全头部**: ```python response.headers.update({ "Strict-Transport-Security": "max-age=31536000", "Content-Security-Policy": "default-src 'self'" })
|