Align session verification logic with osu-web

Updated session verification method selection to match osu-web's State.php:36 logic, using SUPPORT_TOTP_VERIFICATION_VER for version checks and prioritizing TOTP when available. Added example environment files for osu-web-master to support local, dusk, and testing setups.
This commit is contained in:
咕谷酱
2025-10-12 03:34:38 +08:00
parent 0e2df8dfef
commit a10c07dc57
6 changed files with 371 additions and 7 deletions

View File

@@ -121,12 +121,12 @@ async def get_client_user(
verify_method = await LoginSessionService.get_login_method(user.id, token.id, redis)
if verify_method is None:
# 智能选择验证方式(有TOTP优先TOTP
# 智能选择验证方式(参考 osu-web State.php:36
totp_key = await user.awaitable_attrs.totp_key
verify_method = "totp" if totp_key is not None and api_version >= SUPPORT_TOTP_VERIFICATION_VER else "mail"
# 设置选择的验证方法到Redis中避免重复选择
if api_version >= 20250913:
if api_version >= SUPPORT_TOTP_VERIFICATION_VER:
await LoginSessionService.set_login_method(user.id, token.id, verify_method, redis)
# 返回符合 osu! API 标准的错误响应

View File

@@ -338,8 +338,13 @@ async def oauth_token(
# 检查是否为新位置登录
trusted_device = await LoginSessionService.check_trusted_device(db, user_id, ip_address, user_agent, web_uuid)
# 根据 osu-web 逻辑确定验证方法:
# 1. 如果 API 版本支持 TOTP 且用户启用了 TOTP则始终要求 TOTP 验证(无论是否为信任设备)
# 2. 否则,如果是新设备且启用了邮件验证,则要求邮件验证
# 3. 否则,不需要验证或自动验证
session_verification_method = None
if settings.enable_totp_verification and totp_key is not None and api_version >= SUPPORT_TOTP_VERIFICATION_VER:
if api_version >= SUPPORT_TOTP_VERIFICATION_VER and settings.enable_totp_verification and totp_key is not None:
# TOTP 验证优先(参考 osu-web State.php:36
session_verification_method = "totp"
await LoginLogService.record_login(
db=db,

View File

@@ -88,10 +88,9 @@ async def verify_session(
try:
totp_key: TotpKeys | None = await current_user.awaitable_attrs.totp_key
if verify_method is None:
# 智能选择验证方法参考osu-web实现
# 智能选择验证方法参考osu-web实现 State.php:36
# API版本较老或用户未设置TOTP时强制使用邮件验证
# print(api_version, totp_key)
verify_method = "mail" if api_version < 20240101 or totp_key is None else "totp"
verify_method = "mail" if api_version < SUPPORT_TOTP_VERIFICATION_VER or totp_key is None else "totp"
await LoginSessionService.set_login_method(user_id, token_id, verify_method, redis)
login_method = verify_method
@@ -210,7 +209,9 @@ async def reissue_verification_code(
return SessionReissueResponse(success=False, message="当前会话不需要验证")
verify_method: str | None = (
"mail" if api_version < 20250913 else await LoginSessionService.get_login_method(user_id, token_id, redis)
"mail"
if api_version < SUPPORT_TOTP_VERIFICATION_VER
else await LoginSessionService.get_login_method(user_id, token_id, redis)
)
if verify_method != "mail":
return SessionReissueResponse(success=False, message="当前会话不支持重新发送验证码")