3
This commit is contained in:
@@ -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(),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
"""密码哈希与 Token 工具。
|
||||
|
||||
密码:Argon2id(argon2-cffi)
|
||||
Token:secrets.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 token(22 字符)。"""
|
||||
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()
|
||||
Reference in New Issue
Block a user