This commit is contained in:
amb
2026-09-01 13:00:36 +08:00
parent 1d8621717a
commit dfd38c99a0
35 changed files with 3141 additions and 21 deletions
+1 -1
View File
@@ -119,7 +119,7 @@ async def validation_error_handler(_: Request, exc: RequestValidationError) -> J
content={
"code": "VALIDATION_ERROR",
"message": "请求参数不正确。",
"detail": exc.errors(include_url=False, include_input=False),
"detail": exc.errors(),
},
)
+59
View File
@@ -0,0 +1,59 @@
"""密码哈希与 Token 工具。
密码:Argon2idargon2-cffi
Tokensecrets.token_urlsafe + SHA-256 hash + Fernet 加密
"""
import hashlib
import secrets
from argon2 import PasswordHasher
from argon2.exceptions import VerifyMismatchError
from cryptography.fernet import Fernet
from app.core.config import get_settings
_ph = PasswordHasher()
def hash_password(password: str) -> str:
"""Argon2id 哈希密码。"""
return _ph.hash(password)
def verify_password(password: str, password_hash: str) -> bool:
"""验证密码。"""
try:
return _ph.verify(password_hash, password)
except VerifyMismatchError:
return False
def generate_token() -> str:
"""生成 128bit 熵 URL-safe token22 字符)。"""
return secrets.token_urlsafe(16)
def hash_token(token: str) -> str:
"""SHA-256 哈希 token(用于数据库存储和查询)。"""
return hashlib.sha256(token.encode()).hexdigest()
def get_fernet() -> Fernet:
"""从 SECRET_KEY 派生 Fernet 实例(用于加密存储 token 原文)。"""
settings = get_settings()
# 将 SECRET_KEY 转为 32 字节 Fernet key(简单派生,MVP 够用)
key = hashlib.sha256(settings.secret_key.encode()).digest()
import base64
return Fernet(base64.urlsafe_b64encode(key))
def encrypt_token(token: str) -> str:
"""Fernet 加密 token 原文。"""
return get_fernet().encrypt(token.encode()).decode()
def decrypt_token(encrypted: str) -> str:
"""Fernet 解密 token 原文。"""
return get_fernet().decrypt(encrypted.encode()).decode()