Fix registration: use bcrypt directly and show real API error messages.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-28 13:02:06 +08:00
parent 9f34ce8e07
commit 8652476abc
3 changed files with 18 additions and 10 deletions
+4 -5
View File
@@ -1,20 +1,19 @@
import bcrypt
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from typing import Any from typing import Any
from jose import jwt from jose import jwt
from passlib.context import CryptContext
from app.core.config import settings from app.core.config import settings
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def verify_password(plain_password: str, hashed_password: str) -> bool: def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password) return bcrypt.checkpw(plain_password.encode("utf-8"), hashed_password.encode("utf-8"))
def get_password_hash(password: str) -> str: def get_password_hash(password: str) -> str:
return pwd_context.hash(password) return bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()).decode("utf-8")
def create_access_token(subject: str, expires_delta: timedelta | None = None) -> str: def create_access_token(subject: str, expires_delta: timedelta | None = None) -> str:
-1
View File
@@ -6,7 +6,6 @@ alembic==1.14.0
pydantic==2.10.3 pydantic==2.10.3
pydantic-settings==2.6.1 pydantic-settings==2.6.1
python-jose[cryptography]==3.3.0 python-jose[cryptography]==3.3.0
passlib[bcrypt]==1.7.4
bcrypt==4.2.1 bcrypt==4.2.1
python-multipart==0.0.20 python-multipart==0.0.20
httpx==0.28.1 httpx==0.28.1
+14 -4
View File
@@ -1,8 +1,18 @@
import { LockOutlined, UserOutlined } from '@ant-design/icons' import { LockOutlined, UserOutlined } from '@ant-design/icons'
import { Button, Card, Form, Input, Tabs, Typography, message } from 'antd' import { Button, Card, Form, Input, Tabs, Typography, message } from 'antd'
import axios from 'axios'
import { Navigate, useNavigate } from 'react-router-dom' import { Navigate, useNavigate } from 'react-router-dom'
import { useAuth } from '../context/AuthContext' import { useAuth } from '../context/AuthContext'
function apiErrorMessage(error: unknown, fallback: string) {
if (axios.isAxiosError(error)) {
const detail = error.response?.data?.detail
if (typeof detail === 'string') return detail
if (Array.isArray(detail) && detail[0]?.msg) return detail[0].msg
}
return fallback
}
export default function LoginPage() { export default function LoginPage() {
const { user, login, register, loading } = useAuth() const { user, login, register, loading } = useAuth()
const navigate = useNavigate() const navigate = useNavigate()
@@ -16,8 +26,8 @@ export default function LoginPage() {
await login(values.username, values.password) await login(values.username, values.password)
message.success('登录成功') message.success('登录成功')
navigate('/') navigate('/')
} catch { } catch (error) {
message.error('用户名或密码错误') message.error(apiErrorMessage(error, '用户名或密码错误'))
} }
} }
@@ -30,8 +40,8 @@ export default function LoginPage() {
await register(values.username, values.password) await register(values.username, values.password)
message.success('注册成功') message.success('注册成功')
navigate('/') navigate('/')
} catch { } catch (error) {
message.error('注册失败,用户名可能已存在') message.error(apiErrorMessage(error, '注册失败,请稍后重试'))
} }
} }