Update files
This commit is contained in:
parent
354d9aaedd
commit
453d2bf6d2
|
|
@ -5,6 +5,7 @@ from datetime import datetime, timedelta
|
|||
from typing import Optional
|
||||
from jose import JWTError, jwt
|
||||
from passlib.context import CryptContext
|
||||
import bcrypt
|
||||
from fastapi import HTTPException, status, Depends, Cookie, Header
|
||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||
|
||||
|
|
@ -12,7 +13,12 @@ from config import settings
|
|||
from database import users_collection, moderation_admins_collection
|
||||
|
||||
# Password hashing
|
||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||
# Используем bcrypt с явной обрезкой паролей до 72 байт
|
||||
pwd_context = CryptContext(
|
||||
schemes=["bcrypt"],
|
||||
deprecated="auto",
|
||||
bcrypt__ident="2b" # Используем современный формат bcrypt
|
||||
)
|
||||
|
||||
# JWT bearer
|
||||
security = HTTPBearer(auto_error=False)
|
||||
|
|
@ -50,10 +56,51 @@ def hash_password(password: str) -> str:
|
|||
else:
|
||||
print(f"[Auth] ✅ Пароль в пределах лимита (72 байта)")
|
||||
|
||||
# ВАЖНО: passlib/bcrypt может проверять длину пароля ВНУТРИ библиотеки
|
||||
# Обрезаем пароль до 72 байт ПЕРЕД передачей в pwd_context.hash()
|
||||
# Это гарантирует, что пароль никогда не превысит лимит
|
||||
password_bytes_final = password_bytes[:72]
|
||||
password_final = password_bytes_final.decode('utf-8', errors='strict')
|
||||
|
||||
print(f"[Auth] Финальная длина в байтах: {len(password_bytes_final)}")
|
||||
print(f"[Auth] Финальный пароль (repr): {repr(password_final)}")
|
||||
print(f"[Auth] Финальный пароль (len): {len(password_final)} символов")
|
||||
|
||||
# Дополнительная проверка: убедимся, что после декодирования длина в байтах не изменилась
|
||||
password_final_bytes_check = password_final.encode('utf-8')
|
||||
if len(password_final_bytes_check) > 72:
|
||||
print(f"[Auth] ⚠️ После декодирования длина стала {len(password_final_bytes_check)} байт, обрезаем еще раз")
|
||||
password_final = password_final_bytes_check[:72].decode('utf-8', errors='ignore')
|
||||
password_final_bytes_check = password_final.encode('utf-8')
|
||||
|
||||
print(f"[Auth] Финальная проверка: {len(password_final_bytes_check)} байт")
|
||||
|
||||
try:
|
||||
result = pwd_context.hash(password)
|
||||
print(f"[Auth] ✅ Пароль успешно захеширован")
|
||||
# Используем прямой вызов bcrypt для обхода проблемы с passlib
|
||||
# Обрезаем пароль до 72 байт и передаем как bytes
|
||||
password_bytes_for_bcrypt = password_final_bytes_check[:72]
|
||||
|
||||
# Генерируем соль и хешируем пароль
|
||||
salt = bcrypt.gensalt(rounds=10)
|
||||
hashed = bcrypt.hashpw(password_bytes_for_bcrypt, salt)
|
||||
|
||||
# Конвертируем bytes в строку для хранения
|
||||
result = hashed.decode('utf-8')
|
||||
print(f"[Auth] ✅ Пароль успешно захеширован через прямой bcrypt")
|
||||
return result
|
||||
except ValueError as e:
|
||||
# Если bcrypt все равно выдает ошибку, попробуем обрезать до 71 байта
|
||||
error_msg = str(e).lower()
|
||||
if "72 bytes" in error_msg or "longer than" in error_msg or "truncate" in error_msg:
|
||||
print(f"[Auth] ⚠️ Bcrypt все равно жалуется на длину, обрезаем до 71 байта")
|
||||
password_bytes_safe = password_bytes[:71]
|
||||
salt = bcrypt.gensalt(rounds=10)
|
||||
hashed = bcrypt.hashpw(password_bytes_safe, salt)
|
||||
result = hashed.decode('utf-8')
|
||||
print(f"[Auth] ✅ Пароль успешно захеширован после обрезки до 71 байта")
|
||||
return result
|
||||
print(f"[Auth] ❌ ValueError: {e}")
|
||||
raise
|
||||
except Exception as e:
|
||||
print(f"[Auth] ❌ Ошибка при хешировании: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
|
|
@ -73,11 +120,17 @@ def verify_password(plain_password: str, hashed_password: str) -> bool:
|
|||
# Bcrypt has a maximum password length of 72 bytes
|
||||
# Truncate if necessary (encode to bytes first to get accurate byte length)
|
||||
password_bytes = plain_password.encode('utf-8')
|
||||
if len(password_bytes) > 72:
|
||||
# Обрезаем до первых 72 байт (так же, как при хешировании)
|
||||
plain_password = password_bytes[:72].decode('utf-8', errors='ignore')
|
||||
print(f"[Auth] ⚠️ Пароль при проверке обрезан до 72 байт (было {len(password_bytes)} байт)")
|
||||
return pwd_context.verify(plain_password, hashed_password)
|
||||
password_bytes_final = password_bytes[:72]
|
||||
|
||||
# Используем прямой вызов bcrypt для проверки
|
||||
try:
|
||||
hashed_bytes = hashed_password.encode('utf-8')
|
||||
return bcrypt.checkpw(password_bytes_final, hashed_bytes)
|
||||
except Exception as e:
|
||||
print(f"[Auth] ❌ Ошибка при проверке пароля: {type(e).__name__}: {e}")
|
||||
# Fallback на passlib
|
||||
plain_password_final = password_bytes_final.decode('utf-8', errors='ignore')
|
||||
return pwd_context.verify(plain_password_final, hashed_password)
|
||||
|
||||
|
||||
def create_access_token(user_id: str, expires_delta: Optional[timedelta] = None) -> str:
|
||||
|
|
|
|||
Loading…
Reference in New Issue