fix(login): 登录 token 从响应头 Token 提取落地(后端 Content.code 恒返 null)

This commit is contained in:
ozh 2026-09-16 17:11:27 +08:00
parent d3f9a6ae54
commit 86234d4f1f
4 changed files with 40 additions and 3 deletions

View File

@ -31,8 +31,9 @@ export interface WxUserInfo {
// 完整登录响应(needUserInfo=false 时) // 完整登录响应(needUserInfo=false 时)
export interface WxLoginResult { export interface WxLoginResult {
userInfo: WxUserInfo userInfo: WxUserInfo
code: string // 登录凭证(token) code: string | null // 后端文档写登录凭证,联调实测恒为 null(token 走响应头)
openId?: string // 首次登录返回,需本地缓存 openId?: string // 首次登录返回,需本地缓存
token?: string // http 层从响应头 Token 提取附加(仅登录接口返回)
} }
// 登录响应联合体:Message 子状态由 http 层附加到 message 字段 // 登录响应联合体:Message 子状态由 http 层附加到 message 字段

View File

@ -118,9 +118,23 @@ export async function request<T>(
console.log(`[http] ${url} 响应 Message=${subState}`, body.Content) console.log(`[http] ${url} 响应 Message=${subState}`, body.Content)
;(body.Content as Record<string, unknown>).message = subState ;(body.Content as Record<string, unknown>).message = subState
} }
// 后端把登录 token 放响应头 Token(仅登录接口返回;Content.code 恒为 null)——附到返回值供登录流程落地
const resToken = pickResponseToken(res.header)
if (resToken) {
console.log(`[http] ${url} 响应头携带 token`)
;(body.Content as Record<string, unknown>).token = resToken
}
return body.Content return body.Content
} }
// 微信运行时响应头 key 统一小写(header.token),HTTP 原文为大写(Token),两侧兼容
function pickResponseToken(header: Record<string, unknown> | undefined): string | null {
if (!header) return null
const raw = header.token ?? header.Token
if (typeof raw !== 'string' || raw === '') return null
return raw
}
request.get = <T>(url: string, params?: Record<string, unknown>, config?: RequestConfig) => request.get = <T>(url: string, params?: Record<string, unknown>, config?: RequestConfig) =>
request<T>(url, params, { ...config, method: 'GET' }) request<T>(url, params, { ...config, method: 'GET' })

View File

@ -43,10 +43,12 @@ export default function Login() {
setLoading(false) setLoading(false)
return return
} }
if (!result.code || !result.userInfo) throw new Error('登录响应缺少凭证') // token 优先取响应头落地(http 层附到 token 字段);Content.code 后端恒返 null 仅作兼容
const token = result.token ?? result.code
if (!token || !result.userInfo) throw new Error('登录响应缺少凭证')
console.log('[login-page] 登录完成,token 已落地') console.log('[login-page] 登录完成,token 已落地')
setNeedAuth(false) setNeedAuth(false)
dispatch(setAuth({ token: result.code, userInfo: result.userInfo })) dispatch(setAuth({ token, userInfo: result.userInfo }))
await reLaunch(ROUTES.HOME) await reLaunch(ROUTES.HOME)
} }

View File

@ -215,4 +215,24 @@ describe('登录态失效踢回登录页', () => {
const res = await request.get('/demo') const res = await request.get('/demo')
expect(res).toMatchObject({ bindKey: 'b-2', message: 'noMobile' }) expect(res).toMatchObject({ bindKey: 'b-2', message: 'noMobile' })
}) })
it('响应头 Token 附加到返回值 token 字段(微信运行时 key 为小写)', async () => {
mockRequest.mockResolvedValue({
statusCode: 200,
header: { token: 'bce72ebe-uuid' },
data: { Code: '200', Message: '', Content: { userInfo: {} } }
})
const res = await request.get('/demo')
expect(res).toMatchObject({ token: 'bce72ebe-uuid' })
})
it('响应头无 Token 时不附加 token 字段', async () => {
mockRequest.mockResolvedValue({
statusCode: 200,
header: { 'Content-Type': 'application/json' },
data: { Code: '200', Message: '', Content: { name: 'x' } }
})
const res = await request.get('/demo')
expect((res as Record<string, unknown>).token).toBeUndefined()
})
}) })