feat(auth): 将iframe通信从用户名改为令牌验证

This commit is contained in:
JiaJun
2026-04-21 17:00:32 +08:00
parent 195cba9d6e
commit a071d07a7c
9 changed files with 126 additions and 67 deletions

View File

@@ -1,7 +1,7 @@
import {useQuery, useQueryClient} from '@tanstack/react-query'
import {type PropsWithChildren, useEffect, useRef, useState} from 'react'
import {login, validateToken} from '@/api/auth.ts'
import {validateToken} from '@/api/auth.ts'
import {userAssets} from '@/api/user.ts'
import {useTranslation} from 'react-i18next'
import {normalizeLanguage} from '@/lib/i18n'
@@ -14,30 +14,20 @@ const HOST_HEIGHT_MESSAGE = 'IFRAME_HEIGHT'
const HOST_READY_INTERVAL = 500
const HOST_READY_RETRY_LIMIT = 20
const HOST_HEIGHT_REPORT_INTERVAL = 250
const TEST_BOOTSTRAP_ENABLED = import.meta.env.VITE_BYPASS_IFRAME_CONTEXT === 'true'
const TEST_BOOTSTRAP_USERNAME = '+60777777777'
const TEST_BOOTSTRAP_LANGUAGE = 'zh'
export function AuthGuide({children}: PropsWithChildren) {
const {t} = useTranslation()
const queryClient = useQueryClient()
const [username, setUsername] = useState(TEST_BOOTSTRAP_ENABLED ? TEST_BOOTSTRAP_USERNAME : '')
const [hostToken, setHostToken] = useState('')
const setUserInfo = useUserStore((state) => state.setUserInfo)
const setAuthInfo = useUserStore((state) => state.setAuthInfo)
const setAssetsInfo = useUserStore((state) => state.setAssetsInfo)
const setLanguage = useUserStore((state) => state.setLanguage)
const clearUserInfo = useUserStore((state) => state.clearUserInfo)
const hasHostContextRef = useRef(false)
const activeUsernameRef = useRef('')
const activeTokenRef = useRef('')
useEffect(() => {
if (TEST_BOOTSTRAP_ENABLED) {
hasHostContextRef.current = true
activeUsernameRef.current = TEST_BOOTSTRAP_USERNAME
setLanguage(TEST_BOOTSTRAP_LANGUAGE)
return
}
const isEmbedded = window.parent !== window
const notifyParentReady = () => {
@@ -59,17 +49,17 @@ export function AuthGuide({children}: PropsWithChildren) {
return
}
const {language, username: nextUsername} = message.payload
const {language, token} = message.payload
if (typeof nextUsername === 'string' && nextUsername.trim()) {
const normalizedUsername = nextUsername.trim()
if (activeUsernameRef.current && activeUsernameRef.current !== normalizedUsername) {
if (typeof token === 'string' && token.trim()) {
const normalizedToken = token.trim()
if (activeTokenRef.current && activeTokenRef.current !== normalizedToken) {
clearUserInfo()
queryClient.removeQueries({queryKey: ['auth-bootstrap']})
}
hasHostContextRef.current = true
activeUsernameRef.current = normalizedUsername
setUsername(normalizedUsername)
activeTokenRef.current = normalizedToken
setHostToken(normalizedToken)
}
if (typeof language === 'string' && language.trim()) {
@@ -106,19 +96,17 @@ export function AuthGuide({children}: PropsWithChildren) {
}, [clearUserInfo, queryClient, setLanguage])
const authBootstrapQuery = useQuery({
queryKey: queryKeys.authBootstrap(username),
enabled: Boolean(username),
queryKey: queryKeys.authBootstrap(hostToken),
enabled: Boolean(hostToken),
queryFn: async () => {
const loginResponse = await login({username})
const userInfo = loginResponse.data.userInfo
const validateResponse = await validateToken(userInfo.token)
const validateResponse = await validateToken(hostToken)
const authInfo = validateResponse.data
const assetsResponse = await userAssets({
session_id: authInfo.session_id,
})
return {
userInfo,
userInfo: {token: hostToken},
authInfo,
assetsInfo: assetsResponse.data,
}
@@ -235,10 +223,10 @@ export function AuthGuide({children}: PropsWithChildren) {
}
}, [])
if (!username || authBootstrapQuery.isPending) {
if (!hostToken || authBootstrapQuery.isPending) {
return (
<div className="flex min-h-screen items-center justify-center bg-[#08070E] px-6 text-center text-[14px] text-white/68">
{!username && !TEST_BOOTSTRAP_ENABLED ? t('auth.waitingForHostContext') : t('auth.loadingAccountData')}
{!hostToken ? t('auth.waitingForHostContext') : t('auth.loadingAccountData')}
</div>
)
}