From 11ad888ee78e8cc3b371fbdbfed84acdb8e97c93 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Wed, 8 Jul 2026 14:52:21 +0800 Subject: [PATCH] =?UTF-8?q?fix(usercenter):=20=E5=88=B7=E6=96=B0=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E5=8D=B3=E8=A2=AB=E7=99=BB=E5=87=BA=20=E2=80=94?= =?UTF-8?q?=E2=80=94=20refresh=20=E6=94=B9=E7=94=A8=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E4=BD=93=E4=BC=A0=20token(=E4=BF=AE=E8=87=B4=E5=91=BD=E9=89=B4?= =?UTF-8?q?=E6=9D=83=20bug)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因:服务端 POST /v1/auth/refresh 从**请求体** {refresh_token} 读取(handler.go Refresh + 原生 Flutter auth_api.dart 均如此),但 web 客户端 refresh() 误把 refresh token 放进 X-Refresh-Token **请求头**(只有 /auth/logout 读该头)。服务端拿到空 body → 400 auth.invalid_request → 客户端 catch → clearSession → **每次刷新页面即被登出**。 线上实测证实:POST 带头无体 → invalid_request(空);带体 {refresh_token} → invalid_token (正常解析)。故服务端读体、web 发头 = 必然掉线。 改:web refresh() 改用 body:{ refresh_token } 传参(与原生客户端、服务端一致); 无需改/重部署服务端。logout 仍走 X-Refresh-Token 头(服务端 logout 读头,匹配)。 Co-Authored-By: Claude Opus 4.8 --- web/usercenter/lib/api/http.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/web/usercenter/lib/api/http.ts b/web/usercenter/lib/api/http.ts index 9ee4254..4e7b2be 100644 --- a/web/usercenter/lib/api/http.ts +++ b/web/usercenter/lib/api/http.ts @@ -161,11 +161,14 @@ export class HttpClient implements ApiClient { async refresh(): Promise { const rt = getRefreshToken(); if (!rt) throw new ApiError({ code: 'unauthorized', message_zh: '登录已失效', message_en: 'Session expired' }); + // 服务端 /v1/auth/refresh 从 **请求体** {refresh_token} 读取(与原生 Flutter 客户端 + // auth_api.dart 一致);此处曾误用 X-Refresh-Token 头(仅 /auth/logout 读头),导致 + // 服务端拿到空 token → 400 invalid_request → 每次刷新页面即被登出。改回 body。 const r = await this.request('/v1/auth/refresh', { method: 'POST', auth: false, allowRefresh: false, - refreshToken: rt, + body: { refresh_token: rt }, }); const session = mapSession(r); setSession(session);