diff --git a/src/main.ts b/src/main.ts index 6c009ad..d2eebed 100644 --- a/src/main.ts +++ b/src/main.ts @@ -72,12 +72,30 @@ router.beforeEach(async (to, from , next) => { } } } - // switched unionid + // switched unionid(URL 与当前会话不一致时) if (to.query.unionid && store.unionid !== to.query.unionid) { - cookie.set(HtyUnionIDToken, to.query.unionid); + const rawQ = to.query.unionid; + const qUnionStr = String(Array.isArray(rawQ) ? rawQ[0] : rawQ || ''); + // 已登录且 URL 中的 unionid 与当前用户不同:多为带毒分享链接,剥离身份参数而非 logout + if (store.current.hty_id && qUnionStr) { + const cur = store.current as { union_id?: string }; + const currentUnion = String( + cur.union_id != null && cur.union_id !== '' ? cur.union_id : store.unionid || '' + ); + if (currentUnion && qUnionStr !== currentUnion) { + const nextQuery = { ...to.query } as Record; + delete nextQuery.unionid; + delete nextQuery.openid; + delete nextQuery.status; + await router.replace({ path: to.path, query: nextQuery }); + next(); + return; + } + } + cookie.set(HtyUnionIDToken, qUnionStr); logout(); - await login(to.query.toString()) - next() + await login(qUnionStr); + next(); return; } let {enabled, is_registered, roles, union_id} = store.current; diff --git a/src/pages/index.vue b/src/pages/index.vue index b6af953..276e8bd 100644 --- a/src/pages/index.vue +++ b/src/pages/index.vue @@ -50,6 +50,7 @@ import { showConfirmDialog, } from "vant"; import { CurrentUserRole } from "~/utils"; +import { sanitizeMiniProgramWebViewPathForRouter } from "~/utils/wxMiniProgramWebViewShare"; export default defineComponent({ components: { @@ -97,7 +98,8 @@ export default defineComponent({ console.log("page_path...", page_path, decodeURIComponent(page_path)) if (page_path) { - await router.push(decodeURIComponent(page_path)) + const inner = sanitizeMiniProgramWebViewPathForRouter(decodeURIComponent(page_path)) + await router.push(inner) return; } diff --git a/src/utils/wxMiniProgramWebViewShare.ts b/src/utils/wxMiniProgramWebViewShare.ts new file mode 100644 index 0000000..bd99233 --- /dev/null +++ b/src/utils/wxMiniProgramWebViewShare.ts @@ -0,0 +1,42 @@ +/** + * 小程序 WebView 分享 / page_path 里可能携带上一用户的 unionid、openid、status 等, + * 接收方打开后会导致串号或误登。从「路径 + 查询」字符串中剥离这些参数后再交给 vue-router。 + */ +const WEBVIEW_IDENTITY_QUERY_KEYS = [ + 'unionid', + 'openid', + 'status', + 'nickName', + 'avatarUrl', + 'ts', + 'scene', +] as const; + +export function sanitizeMiniProgramWebViewPathForRouter(decodedPathOrUrl: string): string { + const raw = decodedPathOrUrl.trim(); + if (!raw || raw === '/') { + return '/'; + } + let pathPart = raw; + let search = ''; + const q = raw.indexOf('?'); + if (q === 0) { + pathPart = '/'; + search = raw.slice(1); + } else if (q > 0) { + pathPart = raw.slice(0, q) || '/'; + search = raw.slice(q + 1); + } + if (!pathPart.startsWith('/')) { + pathPart = `/${pathPart}`; + } + if (!search) { + return pathPart; + } + const params = new URLSearchParams(search); + for (const key of WEBVIEW_IDENTITY_QUERY_KEYS) { + params.delete(key); + } + const rest = params.toString(); + return rest ? `${pathPart}?${rest}` : pathPart; +} diff --git a/weapp/pages/index/index.js b/weapp/pages/index/index.js index e50c42b..ff5b657 100644 --- a/weapp/pages/index/index.js +++ b/weapp/pages/index/index.js @@ -211,8 +211,29 @@ Page({ onShareAppMessage({from, target, webViewUrl}) { log.info("share", [from, target, webViewUrl].join(" | ")) let pathname = webViewUrl.replace(app.globalData.server, ''); - if (pathname !== '/') { - pathname = encodeURIComponent(pathname) + // 分享勿带 WebView 入口里的 unionid/openid/status 等,避免接收方串号 + if (pathname && pathname !== '/') { + try { + const q = pathname.indexOf('?') + let base = pathname + let search = '' + if (q === 0) { + base = '/' + search = pathname.slice(1) + } else if (q > 0) { + base = pathname.slice(0, q) || '/' + search = pathname.slice(q + 1) + } + if (search) { + const sp = new URLSearchParams(search) + ;['unionid', 'openid', 'status', 'nickName', 'avatarUrl', 'ts', 'scene'].forEach((k) => sp.delete(k)) + const rest = sp.toString() + pathname = rest ? `${base}?${rest}` : (base || '/') + } + } catch (e) { + log.info('share strip query skip', e) + } + pathname = pathname === '/' ? '/' : encodeURIComponent(pathname) } const promise = new Promise(resolve => { setTimeout(() => {