FastAPI中的Pydantic密码验证机制与实现
title: FastAPI中的Pydantic密码验证机制与实现


输入数据 → 基础类型检查 → 长度验证 → 复杂度验证 → 泄露检测 → 最终校验结果
from pydantic import BaseModel, SecretStr, validator
class UserCreate(BaseModel):
username: str
password: SecretStr
email: str
@validator('password')
def validate_password(cls, v):
return v
@validator('password')
def validate_length(cls, v):
if len(v.get_secret_value()) < 10:
raise ValueError("密码至少需要10个字符")
if len(v.get_secret_value()) > 128:
raise ValueError("密码最长不能超过128个字符")
return v
import re
@validator('password')
def validate_complexity(cls, v):
password = v.get_secret_value()
patterns = [
r'(?=.*[A-Z])', # 至少一个大写字母
r'(?=.*[a-z])', # 至少一个小写字母
r'(=.*\d)', # 至少一个数字
r'(?=.*[!@#$%^&*()_+])' # 至少一个特殊字符
]
if not all(re.search(p, password) for p in patterns):
raise ValueError("密码必须包含大小写字母、数字和特殊字符")
return v
import hashlib
def is_password_compromised(password: str) -> bool:
# 这里使用前5位SHA1模拟HIBP API
sha1_hash = hashlib.sha1(password.encode()).hexdigest().upper()
prefix = sha1_hash[:5]
# 示例泄露密码库(实际应调用API)
compromised_hashes = {
'5BAA6': ['5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8']
}
return sha1_hash in compromised_hashes.get(prefix, [])
from fastapi import APIRouter
router = APIRouter()
@router.post("/register")
async def register_user(user: UserCreate):
if is_password_compromised(user.password.get_secret_value()):
raise HTTPException(400, "该密码已被确认泄露,请更换")
# 这里添加数据库存储逻辑
return {"message": "用户注册成功"}
from pydantic import ValidationError
try:
UserCreate(**request_data)
except ValidationError as e:
print(e.errors())
pip install fastapi uvicorn pydantic-settings python-multipart
uvicorn main:app --reload
POST /register HTTP/1.1
Content-Type: application/json
{
"username": "new_user",
"password": "WeakPassword123!",
"email": "user@example.com"
}
评论
发表评论