From 9a342e7ea69bff4739fbff0802fbdb08d43f131a Mon Sep 17 00:00:00 2001 From: yml2213 Date: Sat, 19 Sep 2026 11:06:32 +0800 Subject: [PATCH] =?UTF-8?q?feat(pdd-extension):=20=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E5=8D=87=E7=BA=A7=E8=87=B3=20v1.2.0=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E9=98=B2=E4=BC=91=E7=9C=A0=E5=BF=83=E8=B7=B3=E3=80=81=E4=BC=9A?= =?UTF-8?q?=E8=AF=9D=E4=B8=BB=E5=8A=A8=E7=BB=AD=E6=9C=9F=E4=B8=8E=E8=B6=85?= =?UTF-8?q?=E6=97=B6=E5=BC=B9=E7=AA=97=E7=A7=92=E7=BA=A7=E6=8B=A6=E6=88=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增 content.js 页面级保活引擎,自动注入拼多多商家后台 (mms.pinduoduo.com); 2. 主动防休眠与静默续期:每 2 分钟向 MMS 接口发送轻量只读心跳并派发微动作,主动刷新服务端 PASS_ID 有效期,从根本上阻止空闲弹窗生成; 3. 超时弹窗秒级自动拦截:使用 MutationObserver 实时监听 DOM,毫秒级捕获「当前页面停留时间过长」弹窗并自动点击「刷新」,彻底解决页面挂死导致 Cookie 会话过期被踢出账号的问题; 4. 后台长效平滑刷新:后台标签页静置超 25 分钟自动执行无感安全重载,保障 CSRF Token 与会话 24 小时鲜活; 5. 日志链路打通:将页面防休眠、弹窗拦截与周期刷新事件接入扩展日志控制台。 --- apps/extensions/pdd-cookie-sync/README.md | 10 +- apps/extensions/pdd-cookie-sync/background.js | 33 ++- apps/extensions/pdd-cookie-sync/content.js | 216 ++++++++++++++++++ apps/extensions/pdd-cookie-sync/manifest.json | 15 +- apps/extensions/pdd-cookie-sync/popup.html | 2 +- 5 files changed, 266 insertions(+), 10 deletions(-) create mode 100644 apps/extensions/pdd-cookie-sync/content.js diff --git a/apps/extensions/pdd-cookie-sync/README.md b/apps/extensions/pdd-cookie-sync/README.md index 94576989..b78040bb 100644 --- a/apps/extensions/pdd-cookie-sync/README.md +++ b/apps/extensions/pdd-cookie-sync/README.md @@ -11,14 +11,20 @@ - 自动在后台提取新鲜的会话凭证(包含 `PASS_ID`、`rckk` 等); - 内置 SHA-256 指纹比对去重机制,无实质变动时不发起网络请求,绝不浪费带宽与频控。 -2. **端到端信封加密(End-to-End Envelope Encryption)**: +2. **主动防休眠与防退出引擎(v1.2.0 新增 Anti-Logout Engine)**: + - **静默会话续期**:定时(每 2 分钟)自动调用轻量后台接口,主动刷新拼多多服务端 `PASS_ID` 的 TTL 有效期; + - **前端防休眠心跳**:向页面派发微弱活跃事件,重置 MMS 前端空闲计时器,从根源阻止「页面停留时间过长」弹窗产生; + - **秒级弹窗拦截**:DOM 监听器毫秒级捕获停留过长弹窗并自动秒点「刷新」,彻底避免页面挂死导致 Session 过期被强制踢出登录; + - **周期平滑刷新**:长时间挂机自动无感重载,确保 24 小时保持登录与 Token 鲜活。 + +3. **端到端信封加密(End-to-End Envelope Encryption)**: - **传输层**:强制走 HTTPS / TLS 1.3 通道; - **应用层**:使用浏览器原生 Web Crypto API 生成随机 256 位 AES-GCM 对称密钥; - **非对称公钥包装**:使用服务端的 RSA-2048 公钥(RSA-OAEP SHA-256)加密 AES 密钥; - **防重放与防篡改**:每个数据包附带 60 秒失效时间戳与加密 Nonce,服务端做幂等校验,AES-GCM Auth Tag 确保任意环节防篡改。 - **无私钥泄漏风险**:扩展仅内置/获取公钥,即使他人获取插件源码也绝对无法解密回传数据包。 -3. **双向鉴权与店铺绑定(Pairing Token)**: +4. **双向鉴权与店铺绑定(Pairing Token)**: - 每个店铺在管理后台均有独立的 `syncToken`; - 只有持有该配对密钥的插件上报才会被服务端接受。 diff --git a/apps/extensions/pdd-cookie-sync/background.js b/apps/extensions/pdd-cookie-sync/background.js index ea131a40..09be43f3 100644 --- a/apps/extensions/pdd-cookie-sync/background.js +++ b/apps/extensions/pdd-cookie-sync/background.js @@ -380,25 +380,48 @@ chrome.cookies.onChanged.addListener((changeInfo) => { } }) -// 定时任务:每隔 30 分钟进行一次轻量巡检与必要保活上报 -chrome.alarms.onAlarm.addListener((alarm) => { +// 定时任务:每隔 15 分钟进行一次轻量巡检、保活上报与页面 Ping +chrome.alarms.onAlarm.addListener(async (alarm) => { if (alarm.name === ALARM_NAME) { syncCookieToServer(false).catch(() => null) + + // 向打开的拼多多商家页面发送保活 Ping + try { + const tabs = await chrome.tabs.query({ url: '*://mms.pinduoduo.com/*' }) + for (const tab of tabs) { + if (tab.id) { + chrome.tabs.sendMessage(tab.id, { action: 'ping_keepalive' }).catch(() => null) + } + } + } catch { + // 忽略查询异常 + } } }) // 扩展安装或更新时注册定时闹钟 chrome.runtime.onInstalled.addListener(() => { chrome.alarms.create(ALARM_NAME, { - periodInMinutes: 30, + periodInMinutes: 15, }) - addExtensionLog('info', '扩展安装/更新', '拼多多 Cookie 保活扩展 v1.1.0 后台服务启动') + addExtensionLog('info', '扩展安装/更新', '拼多多 Cookie 保活扩展 v1.2.0 (含防退出/弹窗拦截引擎) 已启动') // 首次运行尝试同步一次 syncCookieToServer(false).catch(() => null) }) -// 响应来自 popup.js 的前端交互消息 +// 响应来自 popup.js 与 content.js 的交互消息 chrome.runtime.onMessage.addListener((req, _sender, sendResponse) => { + if (req.action === 'content_log') { + const level = req.level || 'info' + const action = req.actionName || req.module || '页面保活' + const message = req.message || '' + const details = req.details || null + addExtensionLog(level, action, message, details).then(() => { + sendResponse({ success: true }) + }) + return true + } + if (req.action === 'trigger_sync') { syncCookieToServer(true).then(sendResponse).catch((err) => { sendResponse({ success: false, message: String(err) }) diff --git a/apps/extensions/pdd-cookie-sync/content.js b/apps/extensions/pdd-cookie-sync/content.js new file mode 100644 index 00000000..cee79e7b --- /dev/null +++ b/apps/extensions/pdd-cookie-sync/content.js @@ -0,0 +1,216 @@ +/** + * Pinduoduo Merchant Page Active Keepalive & Anti-Inactivity Content Script + * 拼多多商家后台页面主动保活、防休眠心跳与超时弹窗秒级拦截注入脚本 + */ + +;(function () { + 'use strict' + + const TAG = '[PDD-KEEPALIVE]' + const HEARTBEAT_INTERVAL_MS = 2 * 60 * 1000 // 每 2 分钟执行一次主动心跳与会话续期 + const AUTO_RELOAD_INTERVAL_MS = 25 * 60 * 1000 // 每 25 分钟自动平滑刷新一次页面以保证全状态新鲜 + let lastUserActivityTime = Date.now() + let isReloading = false + + console.log(`${TAG} 拼多多页面主动保活与防休眠助手已加载:`, window.location.href) + + // 辅助:向 background 记录运行日志 + function reportLog(level, action, message, details = null) { + try { + chrome.runtime.sendMessage({ + action: 'content_log', + level, + module: '页面保活', + actionName: action, + message, + details, + }) + } catch { + // 忽略通信异常 + } + } + + // 1. 监听真实用户操作,记录活跃时间戳 + const userEvents = ['mousemove', 'mousedown', 'keydown', 'scroll', 'touchstart'] + userEvents.forEach((evt) => { + window.addEventListener( + evt, + () => { + lastUserActivityTime = Date.now() + }, + { passive: true }, + ) + }) + + // 2. 模拟轻量用户活动(重置拼多多前端页面的空闲计时器) + function dispatchFakeUserActivity() { + try { + const evt = new MouseEvent('mousemove', { + view: window, + bubbles: true, + cancelable: true, + clientX: Math.floor(Math.random() * 200) + 100, + clientY: Math.floor(Math.random() * 200) + 100, + }) + document.dispatchEvent(evt) + window.dispatchEvent(new Event('focus')) + } catch (e) { + console.warn(`${TAG} 模拟微动作异常:`, e) + } + } + + // 3. 发送轻量级静默 API 心跳(主动向拼多多服务端续期 PASS_ID 与会话 TTL) + async function sendSilentSessionHeartbeat() { + try { + dispatchFakeUserActivity() + + // 选择拼多多商家后台最轻量的只读接口进行探测与续期 + const endpoints = [ + '/mangkhut/mms/recentOrderList?page=1&pageSize=1', + '/home/', + '/orders/list', + ] + const targetEndpoint = endpoints[Math.floor(Math.random() * endpoints.length)] + + const resp = await fetch(targetEndpoint, { + method: 'GET', + credentials: 'include', + headers: { + 'X-Requested-With': 'XMLHttpRequest', + Accept: 'application/json, text/plain, */*', + }, + }) + + if (resp.ok) { + console.log(`${TAG} 服务端会话静默续期成功 (${targetEndpoint})`) + } else if (resp.status === 401 || resp.status === 403) { + reportLog('warn', '会话预警', `页面心跳返回 HTTP ${resp.status},可能需要重新登录`) + } + } catch (err) { + console.warn(`${TAG} 发送静默续期心跳异常:`, err) + } + } + + // 4. 实时拦截超时提示遮罩弹窗(秒级自动点击刷新/恢复) + function scanAndBustInactivityModal() { + if (isReloading) return + + // 拼多多超时弹窗典型文案特征 + const triggerKeywords = [ + '当前页面停留时间过长', + '为了避免数据延迟', + '建议刷新一次页面', + '停留时间过长', + ] + + // 查找所有可能的弹窗/Modal 容器 + const modalContainers = document.querySelectorAll( + '.ant-modal, .pdd-modal, [class*="modal"], [class*="dialog"], [role="dialog"]', + ) + + for (const container of modalContainers) { + const text = container.textContent || '' + const hasKeyword = triggerKeywords.some((kw) => text.includes(kw)) + if (!hasKeyword) continue + + console.warn(`${TAG} 🚨 捕获到拼多多超时休眠弹窗!立即执行秒级自动恢复...`) + reportLog('warn', '弹窗拦截', '捕获到「页面停留时间过长」弹窗,立即自动点击刷新续期会话') + + // 寻找弹窗内的「刷新」或确定按钮 + const buttons = container.querySelectorAll('button, a, [role="button"]') + let clicked = false + + for (const btn of buttons) { + const btnText = (btn.textContent || '').trim() + if (btnText.includes('刷新') || btnText.includes('确定') || btnText.includes('知道了')) { + btn.click() + clicked = true + console.log(`${TAG} ✅ 已自动触发弹窗内【${btnText}】按钮`) + break + } + } + + if (!clicked) { + // 若未找到合适按钮,直接调用页面无感平滑重载 + isReloading = true + console.log(`${TAG} 未找到确定按钮,执行 location.reload()`) + setTimeout(() => { + window.location.reload() + }, 500) + } + return + } + + // 全局文本扫描(兜底非标准 modal 结构) + const allDivs = document.querySelectorAll('div') + for (const div of allDivs) { + if (div.children.length === 0 && div.textContent) { + if (div.textContent.includes('当前页面停留时间过长')) { + const parent = div.closest('div[style*="z-index"]') || div.parentElement + const btn = parent ? parent.querySelector('button') : null + if (btn) { + console.warn(`${TAG} 兜底捕获超时弹窗,触发点击`) + btn.click() + } else { + isReloading = true + window.location.reload() + } + break + } + } + } + } + + // 5. DOM 变化观察器(毫秒级感知弹窗挂载) + const observer = new MutationObserver(() => { + scanAndBustInactivityModal() + }) + + if (document.body) { + observer.observe(document.body, { + childList: true, + subtree: true, + }) + } else { + document.addEventListener('DOMContentLoaded', () => { + observer.observe(document.body, { + childList: true, + subtree: true, + }) + }) + } + + // 6. 定时执行静默会话心跳 + setInterval(() => { + sendSilentSessionHeartbeat() + scanAndBustInactivityModal() + }, HEARTBEAT_INTERVAL_MS) + + // 7. 定时平滑刷新兜底(每 25 分钟:若用户 10 分钟未操作,自动安全刷新当前页面刷新凭证) + setInterval(() => { + const idleTime = Date.now() - lastUserActivityTime + // 如果页面处于静置状态(超过 5 分钟未打字或点击),执行一次平滑刷新保持全局新鲜 + if (idleTime > 5 * 60 * 1000 && !isReloading) { + console.log(`${TAG} 页面静置已超周期,执行安全平滑重载以更新全量会话凭证`) + reportLog('info', '周期刷新', '后台页面静置超 25 分钟,自动平滑重载以保持 Token 绝对新鲜') + isReloading = true + window.location.reload() + } + }, AUTO_RELOAD_INTERVAL_MS) + + // 8. 响应来自 Background 的保活 Ping + chrome.runtime.onMessage.addListener((req, _sender, sendResponse) => { + if (req.action === 'ping_keepalive') { + sendSilentSessionHeartbeat() + scanAndBustInactivityModal() + sendResponse({ status: 'alive', timestamp: Date.now() }) + } + }) + + // 初始化首次扫描与心跳 + setTimeout(() => { + sendSilentSessionHeartbeat() + scanAndBustInactivityModal() + reportLog('info', '页面接入', '拼多多商家后台已成功注入主动保活与防退出引擎') + }, 3000) +})() diff --git a/apps/extensions/pdd-cookie-sync/manifest.json b/apps/extensions/pdd-cookie-sync/manifest.json index a2a88c21..01780167 100644 --- a/apps/extensions/pdd-cookie-sync/manifest.json +++ b/apps/extensions/pdd-cookie-sync/manifest.json @@ -1,8 +1,8 @@ { "manifest_version": 3, "name": "拼多多 Cookie 自动保活同步", - "version": "1.1.0", - "description": "自动嗅探拼多多商家后台新鲜 Cookie 并通过端到端 RSA+AES-GCM 信封加密安全同步至业务总平台", + "version": "1.2.0", + "description": "自动嗅探拼多多商家后台新鲜 Cookie 并通过端到端 RSA+AES-GCM 信封加密安全同步,内置防退出与超时弹窗秒级拦截", "permissions": [ "cookies", "storage", @@ -15,6 +15,17 @@ "http://*/*", "https://*/*" ], + "content_scripts": [ + { + "matches": [ + "https://mms.pinduoduo.com/*", + "*://mms.pinduoduo.com/*" + ], + "js": ["content.js"], + "run_at": "document_end", + "all_frames": false + } + ], "background": { "service_worker": "background.js" }, diff --git a/apps/extensions/pdd-cookie-sync/popup.html b/apps/extensions/pdd-cookie-sync/popup.html index 2c7d501d..692e2bfa 100644 --- a/apps/extensions/pdd-cookie-sync/popup.html +++ b/apps/extensions/pdd-cookie-sync/popup.html @@ -235,7 +235,7 @@
拼多多 Cookie 保活 - v1.1.0 + v1.2.0
未检测