前端开发神器:基于Tampermonkey的自动化Cookie同步解决方案

315 阅读8分钟

前端开发神器:基于Tampermonkey的自动化Cookie同步解决方案

摘要:本文将详细介绍一个基于Vue3+TypeScript开发的Tampermonkey用户脚本项目,该项目实现了跨网页的自动化Cookie管理功能,支持多配置管理、实时同步和智能过滤等特性。

项目背景

在日常开发工作中,我们经常需要在本地开发环境中获取登录状态进行测试,尤其是单点登录系统和微应用架构系统。对于这种需求,有许多成熟的解决方案:

常见解决方案对比

方案优点缺点适用场景
手动复制粘贴Cookie简单直接,无需配置效率低下,容易出错,无法自动更新临时测试
修改hosts文件同域共享Cookie自然共享,无需代码改动需要在后端/nginx配置跨域单机开发
浏览器扩展自动同步零配置,自动化依赖浏览器浏览器环境
现有方案的痛点

当前项目中,使用了vite proxy代理来解决跨域问题,团队采用本地维护一份cookie文件的方式,在项目启动时读取并注入到proxy请求头中。但这种方案存在明显的痛点:

  • 更新频繁:单点登录系统的token会定期刷新,需要频繁更新本地cookie文件,导致项目必须重新运行
  • 手动维护:每次cookie变化都需要手动复制粘贴,效率低下且容易出错
  • 团队协作困难:每个开发者都需要单独维护自己的cookie文件
hosts文件方案
  • 需要在后端/nginx配置跨域,且会影响到其他项目的域名解析
  • 当每次新起域名时也需要配置跨域和hosts
浏览器扩展方案的优势
  • 零后端改动:完全基于前端实现,不需要后端配合
  • 无需服务器权限:不依赖Nginx等服务器配置
  • proxy友好:完美适配现有的代理开发模式
  • 自动化程度高:Cookie变化时自动同步,无需手动干预
  • 真实数据:直接使用生产环境的真实Cookie数据
  • 团队共享:可以快速在团队内推广使用

核心功能特性

自动化Cookie管理

  • 智能提取:从源页面自动提取Cookie数据
  • 自动注入:在目标页面自动注入Cookie,无需手动操作
  • 实时同步:监听Cookie变化,自动重新注入最新数据

多配置支持

  • 独立配置:每个配置项支持独立的源页面和目标页面
  • 灵活匹配:支持通配符的URL模式匹配
  • 启用控制:可以随时启用或禁用特定配置

高级特性

  • Cookie过滤:支持指定需要同步的Cookie,避免不必要的数据传输
  • 持久化存储:使用Tampermonkey API实现数据持久化
  • 丰富API:提供完整的控制台API用于配置管理和调试

技术架构设计

技术栈选择

{
  "frontend": "Vue3 + TypeScript",
  "build": "Vite + vite-plugin-monkey", 
  "runtime": "Tampermonkey",
  "storage": "Tampermonkey GM_API"
}

选择这个技术栈的考虑:

  • Vue3:提供现代化的开发体验和响应式数据管理
  • TypeScript:增强代码的类型安全和可维护性
  • Vite:快速的构建工具,配合vite-plugin-monkey专门针对userscript优化
  • Tampermonkey API:跨域存储和页面操作的强大支持

核心架构设计

graph TB
    A[主入口 main.ts] --> B[AutoCookieManager 协调器]
    B --> C[CookieExtractor 提取器]
    B --> D[CookieStorage 存储管理器]
    B --> E[CookieInjector 注入器]
    
    C --> F[源页面 Cookie 提取]
    D --> G[Tampermonkey 存储API]
    E --> H[目标页面 Cookie 注入]
    
    G --> I[实时变化监听]
    I --> E
    
    B --> J[配置管理系统]
    J --> K[多环境配置]
    K --> L[URL匹配规则]

🔧 核心模块实现

1. Cookie提取器 (CookieExtractor)

export class CookieExtractor {
  private lastCookieString: string = ''

  /**
   * 从当前页面获取所有cookie字符串
   */
  public extractAllCookies(): string {
    return document.cookie || ''
  }

  /**
   * 获取当前cookie并检查是否变化
   */
  public getCookiesIfChanged(): { cookieString: string; hasChanged: boolean } {
    const currentCookies = this.extractAllCookies()
    const hasChanged = currentCookies !== this.lastCookieString
    
    if (hasChanged) {
      this.lastCookieString = currentCookies
    }
    
    return {
      cookieString: currentCookies,
      hasChanged
    }
  }
}
  • 变化检测机制,避免不必要的存储操作
  • 简洁的API设计,易于扩展和测试

2. Cookie存储管理器 (CookieStorage)

export class CookieStorage {
  private readonly baseStorageKey = STORAGE_CONFIG.COOKIE_KEY

  /**
   * 保存cookie字符串到存储
   * 只有当cookie发生变化时才保存
   */
  public async saveCookies(cookieString: string, configKey: string): Promise<boolean> {
    // 检查是否有变化
    const isChanged = await this.isCookieChanged(cookieString, configKey)
    if (!isChanged) {
      return false
    }

    const data: StoredCookieData = {
      cookieString,
      source: window.location.hostname
    }

    const storageKey = this.getStorageKey(configKey)
    await GM_setValue(storageKey, data)
    return true
  }
}
  • 基于配置key生成唯一存储标识
  • 变化检测机制,提高性能
  • 完整的错误处理和调试支持

3. Cookie注入器 (CookieInjector)

export class CookieInjector {
  /**
   * 将cookie字符串解析并设置到当前页面
   */
  public injectCookiesToPage(cookieString: string): void {
    const cookies = this.parseCookieString(cookieString)
    let successCount = 0

    cookies.forEach(cookie => {
      try {
        this.setCookie(cookie.name, cookie.value, {
          path: '/',
          domain: this.getCurrentDomain()
        })
        successCount++
      } catch (error) {
        console.log(`❌ 设置cookie失败: ${cookie.name}`, error)
      }
    })
  }
}
  • 智能Cookie解析,处理各种格式
  • 域名适配,确保Cookie能正确设置
  • 详细的成功/失败统计

4. 主协调器 (AutoCookieManager)

这是整个系统的核心,负责协调各个模块:

export class AutoCookieManager {
  public async init(): Promise<void> {    
    // 从存储中加载配置并与默认配置合并
    await this.loadAndMergeConfigs()
    
    // 根据当前页面决定行为
    const currentUrl = window.location.href
    const matchedConfig = this.findMatchingConfig(currentUrl)
    
    if (matchedConfig) {
      if (this.isSourceUrl(currentUrl, matchedConfig.sourceUrl)) {
        // 源页面:开始抓取cookie
        await this.startCookieExtraction(matchedConfig)
      } else if (this.isTargetUrl(currentUrl, matchedConfig.targetUrls)) {
        // 目标页面:注入cookie
        await this.startCookieInjection(matchedConfig)
      }
    }
  }
}

URL匹配机制

项目实现了强大的URL匹配机制,支持通配符模式:

private matchUrl(url: string, patterns: string[]): boolean {
  return patterns.some(pattern => {
    // 处理通配符模式
    if (pattern === '*') {
      return true // 匹配所有URL
    }
    
    // 将模式转换为正则表达式
    const regexPattern = pattern
      .replace(/\./g, '\\.')          // 转义点号
      .replace(/\+/g, '\\+')          // 转义加号
      .replace(/\(/g, '\\(')          // 转义括号
      .replace(/\)/g, '\\)')
      .replace(/\*/g, '.*')           // * 匹配任意字符
    
    const regex = new RegExp(`^${regexPattern}$`, 'i')
    return regex.test(url)
  })
}

支持的匹配模式

  • * - 匹配任意字符
  • https://example.com/* - 匹配该域名下所有页面
  • http://localhost:*/* - 匹配本地所有端口
  • https://test-*.example.com/* - 匹配所有测试子域名

实时同步机制

项目的一大亮点是实现了跨页面的实时Cookie同步:

private addCookieStorageListener(config: ConfigItem): void {
  const storageKey = `${STORAGE_CONFIG.COOKIE_KEY}_${config.key}`
  
  const listenerId = GM_addValueChangeListener(storageKey, async (key: string, oldValue: any, newValue: any, remote: boolean) => {
    if (remote && newValue) {
      console.log(`🔄 检测到配置 ${config.key} 的cookie存储发生变化,重新注入...`)
      
      // 获取新的cookie字符串并重新注入
      const cookieData = newValue
      if (cookieData && cookieData.cookieString) {
        this.injector.injectCookiesToPage(cookieData.cookieString)
        console.log(`✅ 已重新注入配置 ${config.key} 的最新cookie`)
      }
    }
  })
  
  // 保存监听器ID用于后续清理
  this.cookieChangeListeners.set(config.key, listenerId)
}

实现原理

  1. 使用Tampermonkey的GM_addValueChangeListener监听存储变化
  2. 当其他页面更新Cookie时,目标页面自动接收变化通知
  3. 实时重新注入最新的Cookie数据

🛠️ 配置管理系统

配置数据结构

interface ConfigItem {
  key: string           // 唯一标识符
  name?: string         // 配置名称(可选,用于显示)
  sourceUrl: string     // 源URL(抓取cookie的页面)
  targetUrls: string[]  // 目标URL列表(注入cookie的页面)
  enabledCookies: string[]  // 启用的cookie列表(空数组表示所有cookie)
  enabled?: boolean     // 是否启用此配置(默认true)
}

API接口设计

项目提供了完整的控制台API:

// 📋 配置管理
autoSettingCookieScript.getConfigs()                    // 查看所有配置
autoSettingCookieScript.addConfig(configItem)           // 添加配置
autoSettingCookieScript.updateConfig(key, updates)      // 更新配置
autoSettingCookieScript.removeConfig(key)               // 删除配置

// 🔧 核心功能
autoSettingCookieScript.clearAllCookieData()            // 清除所有存储数据
autoSettingCookieScript.clearPageCookies()              // 清除当前页面Cookie

// 🐛 调试工具
autoSettingCookieScript.showStoredCookies(configKey)    // 查看存储的Cookie
autoSettingCookieScript.showStorageInfo()               // 查看存储信息

使用案例

场景1:本地开发环境Cookie同步

// 添加开发环境配置
await autoSettingCookieScript.addConfig({
  key: "local-dev",
  name: "本地开发环境",
  sourceUrl: "https://prod-admin.example.com/*",
  targetUrls: [
    "http://localhost:3000/*",
    "http://localhost:8080/*",
    "http://127.0.0.1:*/*"
  ],
  enabledCookies: ["access_token", "refresh_token", "user_id"]
})

场景2:多环境Cookie管理

// 测试环境
await autoSettingCookieScript.addConfig({
  key: "test-env",
  sourceUrl: "https://auth.test.example.com/*",
  targetUrls: ["https://app.test.example.com/*"],
  enabledCookies: [] // 同步所有cookie
})

// 预发布环境
await autoSettingCookieScript.addConfig({
  key: "staging-env", 
  sourceUrl: "https://auth.staging.example.com/*",
  targetUrls: ["https://app.staging.example.com/*"],
  enabledCookies: []
})

工作流程

sequenceDiagram
    participant SP as 源页面
    participant TM as Tampermonkey存储
    participant TP as 目标页面
    participant User as 用户
    
    User->>SP: 访问源页面
    SP->>SP: 提取Cookie
    SP->>TM: 存储Cookie数据
    
    User->>TP: 访问目标页面
    TP->>TM: 读取Cookie数据
    TP->>TP: 注入Cookie到页面
    TP->>TM: 监听存储变化
    
    Note over SP,TP: 实时同步
    SP->>TM: Cookie发生变化
    TM->>TP: 通知变化
    TP->>TP: 重新注入新Cookie

项目亮点

1. 模块化架构

  • 清晰的职责分离,每个模块专注单一功能
  • 易于测试和维护
  • 良好的扩展性

2. 智能化特性

  • 自动检测Cookie变化,避免不必要的操作
  • 智能URL匹配,支持复杂的匹配规则
  • 实时同步机制,提供无缝的用户体验

3. 用户友好

  • 丰富的控制台API,便于调试和管理
  • 详细的日志输出,便于问题排查
  • 灵活的配置选项,适应不同使用场景

4. 安全性考虑

  • Cookie过滤机制,只同步必要的数据
  • 域名适配,确保Cookie安全设置
  • 错误处理,避免脚本崩溃

未来规划

  1. UI界面:开发可视化的配置管理界面
  2. Cookie加密:增加Cookie数据的加密存储
  3. 批量操作:支持批量导入/导出配置
  4. 更多匹配规则:支持更复杂的URL匹配模式
  5. 性能优化:进一步优化内存使用和执行效率

总结

这个项目展示了如何使用现代化的前端技术栈来开发Tampermonkey用户脚本,主要技术要点包括:

  • TypeScript类型系统的应用,提高代码质量
  • 模块化设计的实践,增强代码可维护性
  • 事件驱动架构的使用,实现实时同步
  • 配置驱动开发的思想,提高灵活性
  • Tampermonkey API的深度使用,充分利用平台能力

Proxy环境下的技术考虑

在现代前端开发中,很多团队使用proxy代理来解决跨域问题:

// 典型的开发环境proxy配置
export default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: 'https://prod-api.example.com',
        changeOrigin: true,
        secure: true
      }
    }
  }
})

在这种架构下,Auto Cookie方案的技术优势特别明显:

  1. 绕过CORS限制:Tampermonkey脚本可以访问任意域名,不受同源策略限制
  2. 保持开发流程:不需要修改现有的proxy配置,保持原有开发习惯
  3. 真实环境测试:直接使用生产环境Cookie,确保测试的真实性
  4. 零侵入性:对现有项目架构零影响,可以随时启用或禁用

通过这个项目,我们不仅解决了proxy环境下的登录状态管理问题,也探索了在现代前端开发环境中使用Tampermonkey的最佳实践。

结语

Auto Cookie项目是一个实用的开发工具,它展示了如何将现代前端技术与浏览器扩展开发相结合,创造出既实用又优雅的解决方案。通过智能化的Cookie管理,显著提升了开发效率,减少了重复性的手动操作。

如果你也在寻找类似的解决方案,或者对Tampermonkey脚本开发感兴趣,欢迎参考这个项目的设计思路和实现方案。


项目地址GitHub - auto-cookie
作者:李二牛
技术栈:Vue3 + TypeScript + Vite + Tampermonkey

如果这篇文章对你有帮助,欢迎点赞、收藏和分享!有任何问题也欢迎在评论区讨论。