Skip to content

Xinguang/user-switcher

Repository files navigation

User Switcher

一个基于 Electron + React + TypeScript 的 macOS 多账号隔离网页会话管理器。

每个账号都会绑定一个独立的持久化 persist:... partition。用户可以为同一网站创建多个账号容器,按需打开对应窗口,自行登录,关闭后保留会话状态,下次继续复用。

功能

  • 添加账号容器并自动打开专属网页登录窗口
  • 列表展示名称、分组、网址、状态、创建时间、最近打开时间
  • 支持按分组展示账号,并按名称 / 分组 / 网址快速检索
  • 编辑账号名称和默认网址
  • 为指定账号从文件导入 Cookies
  • 查看账号当前 Cookies,包含最后更新时间、来源和过期时间
  • 为指定账号抓取页面自动刷新的候选地址,并选择一个作为后台保活请求
  • 按账号配置定时发起保活请求,尽量在长时间不手动打开的情况下维持登录态
  • 账号窗口里的视频旁边会出现明显区别于网站原生 UI 的 预览 / 下载 悬浮按钮
  • 删除账号元数据并清理对应 session 数据
  • 同账号单窗口限制,重复打开时聚焦已有窗口
  • 账号状态持久化,应用重启后仍可恢复账号列表
  • 配置损坏自动备份并重建空配置
  • 主进程状态变更实时推送到渲染层

技术栈

  • Electron
  • React
  • TypeScript
  • Vite
  • Vitest
  • electron-builder

启动

npm install
npm run dev

开发模式会启动 Vite renderer,并在本地拉起 Electron 主进程。

构建

npm run build

构建产物:

  • dist/:renderer 静态资源
  • dist-electron/:主进程与 preload 编译结果

打包

npm run pack
npm run dist
  • npm run pack:生成未封装目录
  • npm run dist:生成可分发安装包

测试

npm run typecheck
npm test
npm run test:e2e

说明:

  • npm test 覆盖单元测试与集成测试
  • npm run test:e2e 是 UI 端到端测试,走真实 renderer + service + repository 流程

Cookies 导入

列表项里提供 导入 Cookies 按钮,会打开系统文件选择器,并把选中的 Cookie 文件导入到该账号对应的独立 session partition。

当前支持的文件格式:

[
  {
    "name": "sid",
    "value": "abc",
    "domain": ".example.com",
    "path": "/",
    "secure": true,
    "httpOnly": true,
    "sameSite": "Lax"
  }
]

或:

{
  "cookies": [
    {
      "name": "sid",
      "value": "abc",
      "url": "https://example.com/"
    }
  ]
}

说明:

  • 第二种格式兼容 Playwright storageState 里的 cookies
  • 首版只导入 Cookies,不导入 localStorage / IndexedDB / storage state
  • 某些网站仅靠 Cookies 不足以恢复完整登录态,这是站点实现限制,不是导入器本身能完全规避的问题

Cookies 查看

每个账号卡片提供 查看 Cookies 按钮,会读取该账号当前 session 里的 Cookies,并展示:

  • 最后一次保活刷新时间
  • 每条 Cookie 的最后更新时间
  • 这条 Cookie 最近是后台保活刷新的,还是打开页面时自动获取的,或者来自手动导入
  • 当前过期时间或是否为会话级 Cookie

后台保活

每个账号卡片里提供 保活设置 按钮。点击后可以:

  • 新账号创建后默认就是启用后台保活,初始同域页面默认为账号配置里的目标网址

  • 抓取候选地址:自动打开或聚焦该账号页面,并在 20 秒内记录这个页面自己发出的刷新请求

  • 选择一个候选地址:只会列出账号目标地址同域的请求,通常优先选 GETxhr 或主文档刷新请求

  • 设置刷新间隔:应用会在后台按分钟间隔发起一次同 session 的保活请求

  • 立即刷新一次:手动验证当前选择的地址是否还能成功返回

工作方式:

  • 保活请求使用该账号自己的 Electron persist: session 发出,所以会复用这个账号现有 Cookies
  • 如果保活地址返回 302/跳转,应用会跟随跳转,并把最终登录后的同域页面记成后续保活目标
  • 不会定时整页打开网站,只会请求你选中的同域地址;如果你没有手动选择,就默认刷新最近一次打开到的同域页面
  • 保活属于“尽量维持登录态”,不能保证所有站点 30 天后仍然有效

限制:

  • 如果站点登录态依赖页面脚本、动态签名、WebSocket、短期 token、设备指纹或人机校验,单纯刷一个 URL 可能不够
  • 如果候选地址已经失效,可以重新抓取一轮并改选新的地址
  • 只有应用在运行时,后台保活才会继续执行

目录

src/
  main/       Electron 主进程、服务层、IPC、窗口与持久化
  preload/    最小化暴露渲染层 API
  renderer/   React UI
  shared/     共享类型
tests/
  unit/
  integration/
  e2e/

关键模块

  • src/main/repositories/accountRepository.ts 负责 accounts.json 读取、损坏恢复、原子写入。
  • src/main/services/accountService.ts 负责业务规则、状态变更、删除回滚和状态广播。
  • src/main/services/sessionService.ts 负责 partition 命名与 session 清理。
  • src/main/services/windowService.ts 负责账号窗口创建、复用、关闭、幂等清理。
  • src/main/ipc/accountHandlers.ts 负责统一 IPC 返回结构。

本地数据

默认写入用户家目录下的隐藏目录,例如当前应用会使用 ~/.user-switcher/。这样即使删掉 app 包重新打开,配置和持久化 cookies 仍然可以复用。测试或定制部署时可通过环境变量覆盖:

USER_SWITCHER_DATA_DIR=/custom/path npm run dev

目录结构:

~/.user-switcher/
  config/accounts.json
  logs/app.log
  logs/error.log
  temp/
  session/

安全约束

  • 不保存账号密码
  • 不读取外部浏览器 profile 数据库
  • nodeIntegration: false
  • contextIsolation: true
  • preload 仅暴露最小账户管理 API

二期扩展预留

  • 登录态检测
  • 更细粒度的账号会话调试工具
  • Chrome / Edge 当前 profile 一键导入

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors