From 7a1e32688c9c6b902c62b85c88f101e215c2140d Mon Sep 17 00:00:00 2001 From: xcbyy <2578898740@qq.com> Date: Wed, 21 Oct 2026 10:59:22 +0800 Subject: [PATCH] =?UTF-8?q?fix(miniapp):=20=E4=BF=AE=E5=A4=8D=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E6=80=81=E9=94=99=E9=85=8D=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?=20403=EF=BC=88userId=20=E4=B8=8E=20userToken=20=E5=8E=9F?= =?UTF-8?q?=E5=AD=90=E5=86=99=E5=85=A5/=E6=B8=85=E9=99=A4=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - completeLogin 统一接收 sessionToken:有 token 写入、无 token(体验账号回退)清除旧 token,杜绝旧 token 属主与新 userId 不一致 - 微信手机号登录把 token 交给 completeLogin 统一落库 - normalizeUserId 移除历史 101→2006 映射;有 token 但本地 userId 缺失时传 0,由服务端按 token 识别 - 新增 login-identity-consistency.spec.ts(106 套件/706 用例全绿) --- pwuniapp/common/api.js | 10 +++++-- pwuniapp/pages/auth/login.vue | 14 +++++---- .../tests/login-identity-consistency.spec.ts | 29 +++++++++++++++++++ 3 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 server/tests/login-identity-consistency.spec.ts diff --git a/pwuniapp/common/api.js b/pwuniapp/common/api.js index eb1c181..a9e7a44 100644 --- a/pwuniapp/common/api.js +++ b/pwuniapp/common/api.js @@ -564,8 +564,14 @@ function normalizeUserId(uid) { } catch (_) {} } const n = Number(target); - if (n === 101) return 2006; - return (!isNaN(n) && n > 0) ? n : 1001; + const valid = !isNaN(n) && n > 0; + // 已登录(存在会话 token)时身份以服务端 token 为准:若本地 userId 缺失则传 0, + // 避免"旧 token 属主 + 声明的 userId"不一致被服务端判定为以他人身份操作(403)。 + try { + const token = uni.getStorageSync('userToken'); + if (token) return valid ? n : 0; + } catch (_) {} + return valid ? n : 1001; } /** diff --git a/pwuniapp/pages/auth/login.vue b/pwuniapp/pages/auth/login.vue index 0fbeb90..b79cfd1 100644 --- a/pwuniapp/pages/auth/login.vue +++ b/pwuniapp/pages/auth/login.vue @@ -156,7 +156,7 @@ onShow(() => { loadProtocolConfig(); }); -const completeLogin = (userId, customData = {}) => { +const completeLogin = (userId, customData = {}, sessionToken = '') => { if (customData.status === '已封禁' || customData.status === '封禁') { uni.showModal({ title: '账号已封禁', @@ -172,6 +172,13 @@ const completeLogin = (userId, customData = {}) => { uni.hideLoading(); uni.removeStorageSync('user_has_logged_out'); uni.setStorageSync('userId', userId); + // userId 与 token 必须保持一致:无 token 的体验登录要清掉旧 token, + // 否则会出现"旧 token 属主 + 新 userId"→ 服务端判定以他人身份操作(403) + if (sessionToken) { + uni.setStorageSync('userToken', sessionToken); + } else { + uni.removeStorageSync('userToken'); + } uni.setStorageSync('userInfo', { id: userId, nickname: customData.nickname || '微信用户', @@ -251,10 +258,7 @@ const handleGetPhoneNumber = async (e) => { if (res && (res.user || res.userId)) { const userObj = res.user || { id: res.userId, phone: res.phone }; const sessionToken = res.userToken || res.token || ''; - if (sessionToken) { - uni.setStorageSync('userToken', sessionToken); - } - completeLogin(userObj.id, userObj); + completeLogin(userObj.id, userObj, sessionToken); return; } } catch (err) { diff --git a/server/tests/login-identity-consistency.spec.ts b/server/tests/login-identity-consistency.spec.ts new file mode 100644 index 0000000..2e5f175 --- /dev/null +++ b/server/tests/login-identity-consistency.spec.ts @@ -0,0 +1,29 @@ +// 已读取AGENTS.md +import * as fs from 'fs'; +import * as path from 'path'; + +/** + * 第九十批:登录态一致性(userId 与 userToken 不得错配)。 + * 背景:体验账号回退登录只写 userId=1001 却保留旧 token(属主 2010), + * 服务端按 token 身份校验 → 判定"以他人身份操作" → 收藏/通知/优惠券/举报全部 403。 + */ +describe('第九十批登录态一致性闸门', () => { + const root = path.resolve(__dirname, '../../'); + const api = fs.readFileSync(path.join(root, 'pwuniapp/common/api.js'), 'utf-8'); + const login = fs.readFileSync(path.join(root, 'pwuniapp/pages/auth/login.vue'), 'utf-8'); + + it('completeLogin 原子写入 userId 与 token(无 token 时清除旧 token)', () => { + expect(login).toContain('const completeLogin = (userId, customData = {}, sessionToken = \'\')'); + expect(login).toContain('uni.removeStorageSync(\'userToken\')'); + expect(login).toContain('uni.setStorageSync(\'userToken\', sessionToken)'); + }); + + it('微信登录把 token 交给 completeLogin 统一落库', () => { + expect(login).toContain('completeLogin(userObj.id, userObj, sessionToken)'); + }); + + it('normalizeUserId 不再做 101→2006 映射;有 token 时缺失 userId 传 0', () => { + expect(api).not.toContain('if (n === 101) return 2006;'); + expect(api).toContain('if (token) return valid ? n : 0;'); + }); +});