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 typing import Optional
|
||||||
from jose import JWTError, jwt
|
from jose import JWTError, jwt
|
||||||
from passlib.context import CryptContext
|
from passlib.context import CryptContext
|
||||||
|
import bcrypt
|
||||||
from fastapi import HTTPException, status, Depends, Cookie, Header
|
from fastapi import HTTPException, status, Depends, Cookie, Header
|
||||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||||
|
|
||||||
|
|
@ -12,7 +13,12 @@ from config import settings
|
||||||
from database import users_collection, moderation_admins_collection
|
from database import users_collection, moderation_admins_collection
|
||||||
|
|
||||||
# Password hashing
|
# Password hashing
|
||||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
# Используем bcrypt с явной обрезкой паролей до 72 байт
|
||||||
|
pwd_context = CryptContext(
|
||||||
|
schemes=["bcrypt"],
|
||||||
|
deprecated="auto",
|
||||||
|
bcrypt__ident="2b" # Используем современный формат bcrypt
|
||||||
|
)
|
||||||
|
|
||||||
# JWT bearer
|
# JWT bearer
|
||||||
security = HTTPBearer(auto_error=False)
|
security = HTTPBearer(auto_error=False)
|
||||||
|
|
@ -50,10 +56,51 @@ def hash_password(password: str) -> str:
|
||||||
else:
|
else:
|
||||||
print(f"[Auth] ✅ Пароль в пределах лимита (72 байта)")
|
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:
|
try:
|
||||||
result = pwd_context.hash(password)
|
# Используем прямой вызов bcrypt для обхода проблемы с passlib
|
||||||
print(f"[Auth] ✅ Пароль успешно захеширован")
|
# Обрезаем пароль до 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
|
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:
|
except Exception as e:
|
||||||
print(f"[Auth] ❌ Ошибка при хешировании: {type(e).__name__}: {e}")
|
print(f"[Auth] ❌ Ошибка при хешировании: {type(e).__name__}: {e}")
|
||||||
import traceback
|
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
|
# Bcrypt has a maximum password length of 72 bytes
|
||||||
# Truncate if necessary (encode to bytes first to get accurate byte length)
|
# Truncate if necessary (encode to bytes first to get accurate byte length)
|
||||||
password_bytes = plain_password.encode('utf-8')
|
password_bytes = plain_password.encode('utf-8')
|
||||||
if len(password_bytes) > 72:
|
password_bytes_final = password_bytes[:72]
|
||||||
# Обрезаем до первых 72 байт (так же, как при хешировании)
|
|
||||||
plain_password = password_bytes[:72].decode('utf-8', errors='ignore')
|
# Используем прямой вызов bcrypt для проверки
|
||||||
print(f"[Auth] ⚠️ Пароль при проверке обрезан до 72 байт (было {len(password_bytes)} байт)")
|
try:
|
||||||
return pwd_context.verify(plain_password, hashed_password)
|
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:
|
def create_access_token(user_id: str, expires_delta: Optional[timedelta] = None) -> str:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue