同步cookie插件原理及实现示例

目录
  • 为什么需要同步 cookie 的需求?
  • 撸起袖子开始干

为什么需要同步 cookie 的需求?

因为我们公司统一登录、统一认证体系实现方式是通过在公司域名下的 cookie 注入 acces_token 等内容,然后在不同系统间通过携带的 cookie 信息进行认证并跳转到对应系统。

因为本地开发环境 localhost 和公司域名不在同一个域下,导致需要模拟登录后,需要手动将相关 cookie 信息拷贝在 main.js 文件中,注入到 localhost 域名下。这就导致每次换一个用户登录,我就要手动复制下面这些内容,而且当 cookie 过期时也要重复一遍这样的操作,这对一个程序员来说太繁琐了,太麻烦了,严重影响了摸鱼时间

// 每次在开发环境都要手动复制 4 个 cookie 信息
const evnNode = process.env.VUE_APP_ENV
if (evnNode === 'development') {
  document.cookie = 'access_token=xxx'
  document.cookie = 'refresh_token=xxx'
  document.cookie = 'token_since=123'
  document.cookie = 'original_access_token=xxx'
}

所以在这样一个背景下,我开始探索有什么办法能不用每次都手动复制这 4 个复制 cookie 的方案

最初想到的方案是直接通过获取公司域名下的 cookie 信息,但因为浏览器的安全性质,是不能获取跨域的 cookie 信息的,这个时候又想到改造浏览器的安全限制,但这个方案不具有通用性,就先放弃了。第二个考虑的方案是本地起一个 node 中间件,通过这个中间间实现携带 cookie,但是因为实现复杂也放弃了

之后在一次偶然的百度中发现 chrome 插件可以突破跨域的限制,获取到不同域名下的 cookie,然后百度了一下 chrome 插件的开发者文档,找到了监听 cookie 变化的事件,研究到这里,我觉得可以开始实现需求了

撸起袖子开始干

一个 chrome 插件本质也是一个前端应用运行在 chrome 浏览器的环境里,所以直接就选择了 Vue3 + Vite2 进行开发。先用 pnpm create vite 初始化一个 vite 项目,安装好需要使用的 UI 库 Ant Design Vue,删掉无用的内容之后先得到一个基础的项目结构

接下来配置 chrome 插件的信息,chrome 插件主要是在 manifest.json 文件中配置基础信息。在 public 目录下新建一个 manifast.json 文件,文件中有几个配置是比较重要的,这里特别解释一下

manifest_version:定义配置清单的版本,从 Chrome 88 开始就是 V3,我是用的也是 3 这个版本

permissions:申请操作 chrome 的一些操作权限,这个插件里我主要用到的是 storage 和 cookies 的权限

host_permissions:申请有权限操作的域名,这里直接指定所有域名 "<all_urls>" 即可

background:后台运行脚本指定的属性,可以是 HTML,也可以是 JS 文件,主要是用于在后台监听 cookie 变化

插件的 icon 我是在阿里的 iconfont 上下载的,下载时可以选择不同的大小,其他信息就直接附上源码好了

{
  "manifest_version": 3,
  "name": "sync-cookie-extension",
  "version": "1.0.0",
  "description": "开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie",
  "icons": {
    "16": "sources/cookie16.png",
    "32": "sources/cookie32.png",
    "48": "sources/cookie48.png",
    "128": "sources/cookie128.png"
  },
  "action": {
    "default_icon": "sources/cookie48.png",
    "default_title": "解决本地开发 localhost 请求无法携带 cookie 问题",
    "default_popup": "index.html"
  },
  "permissions": ["storage", "cookies"],
  "host_permissions": ["<all_urls>"],
  "background": {
    "service_worker": "background.js",
    "type": "module"
  }
}

然后就是插件的功能开发,根据需求这个插件主要实现的两个功能

  • 支持配置需要同步到本地的域名和 cookie 名称,支持开启和关闭同步
  • 当配置列表中的 cookie 发生变化时,能够将同步至本地

第一个功能就是基于可编辑表格的 CRUD 一套功能,我是用的 Ant Design Vue 来开发的,一套操作下来页面效果是这样的(源码地址

下面就是实现最主要的同步功能:当 from 字段下 cookie name 发上变化时,将 cookie 同步至 to 字段对应的域名下(默认是 localhost )

第一步先要将我们在列表中配置的域名信息存储在 localstorage 中,一方面为了在插件后台中能够获取到需要同步的列表,另一方面当插件刷新时列表信息也不会丢失。然后还要写一个同步 cookie 的方法 updateCookie 方法用于加载时第一次同步 cookie

// 在 useStorage.ts 中定义存储 localstorage 方法和更新 cookie 的方法
import { ICookieTableDataSource, ICookie, TCookieConfig, LIST_KEY } from "../type";
// 增加协议头
function addProtocol(uri: string) {
  return uri.startsWith("http") ? uri : `http://${uri}`;
}
// 移除协议头
function removeProtocol(uri: string) {
  return uri.startsWith("http")
    ? uri.replace("http://", "").replace("https://", "")
    : uri;
}
const useStorage = () => {
  async function updateStorage(list: ICookieTableDataSource[]) {
    await chrome.storage.local.set({ [LIST_KEY]: list });
  }
  async function getStorage(key = LIST_KEY) {
    return await chrome.storage.local.get(key);
  }
  async function updateCookie(config: TCookieConfig) {
    try {
      const cookie = await chrome.cookies.get({
        url: addProtocol(config.from || "url"),
        name: config.cookieName || "name",
      });
      return cookie ? await setCookie(cookie, config) : null;
    } catch (error) {
      console.error("error: ", error);
    }
  }
  function setCookie(cookie: ICookie, config: TCookieConfig) {
    return chrome.cookies.set({
      url: addProtocol(config.to || "url"),
      domain: removeProtocol(config.to || "url"),
      name: cookie.name,
      path: "/",
      value: cookie.value,
    });
  }
  return {
    updateStorage,
    getStorage,
    updateCookie,
  };
};
export default useStorage;

第二步就是在插件首次加载的时候,从 localhost 读取是否开启同步和配置列表,然后读取配置列表的信息更新 cookie

// 读取是否同步开启和配置列表
const dataSource = ref<ICookieTableDataSource[]>(DEFAULT_LIST); // DEFAULT_LIST 是默认最初的同步列表,这样第一次加载插件时 localstorage 为空的话也不用手动在写一遍
const { updateStorage, getStorage, updateCookie } = useStorage();
onMounted(async () => {
  // 初始化开启同步状态
  const openSyncLocal = await getStorage("isOpenSync");
  if (!isEmpty(openSyncLocal)) {
    isOpenSync.value = openSyncLocal.isOpenSync;
  }
  // 从 localStorage 初始化数据
  const storage = await getStorage();
  const domainList = !isEmpty(storage)
    ? (Object.values(storage[LIST_KEY]) as ICookieTableDataSource[])
    : [];
  if (!isEmpty(domainList)) {
    dataSource.value = domainList;
  }
  // 更新 localStorage 和 cookie
  if (!isEmpty(unref(dataSource))) {
    updateStorage(dataSource.value);
    dataSource.value.forEach((item) => {
      updateCookie({
        from: item.from,
        to: item.to,
        cookieName: item.cookieName,
      });
    });
  }
});

第三步当是否开启同步状态和配置列表发生变化时需要更新 localhost,这里使用 watch 监听同步状态的改变,然后再保存同步列表的方法里新增更新 localstorage

watch(isOpenSync, async () => {
  await chrome.storage.local.set({ isOpenSync: isOpenSync.value });
});
async function handleSave(rowId: string) {
  Object.assign(
    dataSource.value.filter((item) => item.id === rowId)[0],
    editableData[rowId]
  );
  delete editableData[rowId];
  // 更新 localStorage
  updateStorage(dataSource.value);
}

到这里已经实现的第一次的 cookie 同步功能,然后就要用到监听 cookie 变化的事件 chrome.cookies.onChanged.addListener 了。我们之前在 manifest.json 文件中配置了 background 这个参数,这个时候就要用上了

"background": {
  "service_worker": "background.js",
  "type": "module"
}

在项目 public 目录下新建 background.js,添加 cookie 改变监听事件函数,然后从 localhost 中获取是否开启同步状态和配置列表,在开启同步的状态下,从列表中找到需要更新的 cookie 同步至本地就可以了

addCookiesChangeEvent();
function addCookiesChangeEvent() {
  console.log("start addCookiesChangeEvent");
  chrome.cookies.onChanged.addListener(async ({ cookie, removed }) => {
    // 判断是否开启同步
    const openSyncObj = await chrome.storage.local.get("isOpenSync");
    const isOpenSync = openSyncObj.isOpenSync;
    if (!isOpenSync) return;
    const storage = await chrome.storage.local.get(["domainList"]);
    if (Object.keys(storage).length === 0) return;
    const domainList = Object.values(storage["domainList"]);
    // 需求更新的 cookie
    const target = domainList.find((item) => {
      return (
        equalDomain(item.from, cookie.domain) && item.cookieName === cookie.name
      );
    });
    if (target) {
      if (removed) {
        removeCookie(cookie, target);
      } else {
        setCookie(cookie, target);
      }
    }
  });
}
function setCookie(cookie, config) {
  return chrome.cookies.set({
    url: addProtocol(config.to || "url"),
    domain: removeProtocol(config.to || "url"),
    name: cookie.name,
    path: "/",
    value: cookie.value,
  });
}
function removeCookie(cookie, config) {
  chrome.cookies.remove({
    url: addProtocol(config.to || "url"),
    name: cookie.name,
  });
}
// 增加协议头
function addProtocol(uri) {
  return uri.startsWith("http") ? uri : `http://${uri}`;
}
// 移除协议头
function removeProtocol(uri) {
  return uri.startsWith("http")
    ? uri.replace("http://", "").replace("https://", "")
    : uri;
}
function equalDomain(domain1, domain2) {
  return addProtocol(domain1) === addProtocol(domain2);
}

到这里同步功能就已经实现了,接下来打包项目 pnpm run build,打开 chrome 浏览器开发者模式,选择“加载解压缩的扩展”,选择打包的 dist 文件安装,如果安装成功的话可以看到这样一个图标

最后测试一下插件的效果,在百度域名下输入一个测试域名,然后在 localhost 下刷新一下,可以看到 cookie 已经成功同步过去了,大功告成

代码我也上传到了 github,有兴趣的话大家也可以 star 支持一波,源码地址

以上就是同步cookie插件原理及实现示例的详细内容,更多关于同步cookie插件的资料请关注我们其它相关文章!

(0)

相关推荐

  • 解决vue项目本地启动时无法携带cookie的问题

    解决vue项目打包部署到服务器上可以正常登录,本地启动时无法携带cookie 说一下问题:公司的老项目,从gitLab上克隆下来,启动之后登录,接口返回登录成功,然后又调用其他的接口的时候返回未登录,查看请求头,未携带cookie,因此调用接口的时候提示未登录. 但是同样的代码打包部署之后一切正常,调接口的时候是携带cookie的,一通百度之后终于解决了. 我用的是谷歌chrome浏览器 解决步骤如下: 1.在浏览器地址栏访问chrome://flags 2.搜索框内搜索SameSite,然后把

  • Vue项目如何设置反向代理和cookie设置问题

    目录 Vue设置反向代理和cookie设置 项目场景 问题描述 原因分析 解决方案 Vue项目使用js-cookie细则 什么是js-cookie 在项目中进行安装 在项目中的入口文件(main.js)全局引入 在项目中使用 Vue设置反向代理和cookie设置 项目场景 最近使用Vue开发一个新的项目,因为服务器还没到,调取后端本地接口,因为请求接口的时候没有跨域,就没开反向代理.后面就被一个很基础的东西踩了坑,就是 cookie的一些知识,记录一下,加深一下印象. 问题描述 联调过程中,发现

  • vue登录页实现使用cookie记住7天密码功能的方法

    问题描述 项目的登录页中,会有要求记住7天密码的功能,本篇文章记录一下写法,主要是使用cookie,注释我写的很详细了,大家可以看一下我写的注释的步骤,还是比较详细的.亲测有效 html部分 代码图示 效果图示 代码粘贴 <el-form ref="form" :model="form" label-width="80px" label-position="top" @submit.native.prevent >

  • 轻量级JS Cookie插件js-cookie的使用方法

    Cookie是网站设计者放置在客户端的小文本文件,一般后台语言使用的比较多,可以实现用户个性化的一些需求.js-cookie插件是一个JS操作cookie的插件,源文件只有3.34 KB,非常轻量级.js-cookie也支持npm和Bower安装和管理.下面看看js-cookie的具体用法. A simple, lightweight JavaScript API for handling cookies Works in all browsers Accepts any character H

  • vue中的cookies缓存存值方式 超简单

    目录 使用vue-cookies插件 第一步:安装 第二步:全局引入 main.js 无需多言 第三步:设置cookies 第四步:获取cookies vue使用缓存遇到的坑总结 (1) good-storage     good-storage库地址 (2) vue-cookie   vue-cookie库地址 (3) vue-cookies   vue-cookies库地址 使用vue-cookies插件 第一步:安装 npm install vue-cookies --save 第二步:全

  • vue3中cookie的详细使用过程

    目录 前言 1.vue中cookie的安装 2.登录过程中cookies的设置 3.在需要的地方拿到之前存入的cookies 总结 前言 cookie使用最多的地方想必是保存用户的账号与密码,可以避免用户每次登录时都要重新输入 1.vue中cookie的安装 在终端中输入命令npm install vue-cookies --save,即可安装cookies,安装之后在main.js文件中写下以下代码 import { createApp } from 'vue' import VueCooki

  • 同步cookie插件原理及实现示例

    目录 为什么需要同步 cookie 的需求? 撸起袖子开始干 为什么需要同步 cookie 的需求? 因为我们公司统一登录.统一认证体系实现方式是通过在公司域名下的 cookie 注入 acces_token 等内容,然后在不同系统间通过携带的 cookie 信息进行认证并跳转到对应系统. 因为本地开发环境 localhost 和公司域名不在同一个域下,导致需要模拟登录后,需要手动将相关 cookie 信息拷贝在 main.js 文件中,注入到 localhost 域名下.这就导致每次换一个用户

  • 简单分析ucenter 会员同步登录通信原理

    1.用户登录discuz,通过logging.php文件中的函数uc_user_login对post过来的数据进行验证,也就是对username和password进行验证. 2.如果验证成功,将调用位于uc_client下client.php文件中的函数uc_user_synlogin,在这个函数中调用 uc_api_post('user', 'synlogin', array('uid'=>$uid)). 3.然后这个函数后向Ucenter的index.php传递数据,index.php接受传

  • c# 线程安全队列的用法原理及使用示例

    什么是线程安全? 答:线程安全是多线程编程时的计算机程序代码中的一个概念.在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况. 在多线程并行的情况下会出现共享数据会线程间读取与写入不一直的情况,为了解决这种情况,通常会使用锁来解决,也就是将并行改为串行.但是在使用穿行违背了使用多线程并发的初衷,这种情况下我们可以考虑采用线程安全结构. 先看下线程安全队列的用法: ConcurrentQueue<int> ts =

  • Java拦截器Interceptor实现原理及代码示例

      1,拦截器的概念 java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行,同时也提供了一种可以提取Action中可重用部分代码的方式.在AOP中,拦截器用于在某个方法或者字段被访问之前,进行拦截然后再之前或者之后加入某些操作.目前,我们需要掌握的主要是Spring的拦截器,Struts2的拦截器不用深究,知道即可. 2,拦截器的原理 大部分时候,拦截器方法都是通过代理的方式来调用的.S

  • php cookie工作原理与实例详解

    在php 中cookie是我们常用到的,但是可能很多朋友都不知道cookie是怎么工作的,下面小编来给大家整理一下关于php cookie 工作原理与一些对于cookie读写操作实例. Cookie和会话状态 做BS开发,这两个概念必不可少,先来个大概了解,没有实际应用很难深入,深入看参考地址! 什么是 Cookie? Cookie 是一小段文本信息,伴随着用户请求和页面在 Web 服务器和浏览器之间传递.用户每次访问站点时,Web 应用程序都可以读取 Cookie 包含的信息. Cookie

  • 快速学习jQuery插件 Cookie插件使用方法

    Cookie是网站设计者放置在客户端的小文本文件.Cookie能为用户提供很多的使得,例如购物网站存储用户曾经浏览过的产品列表,或者门户网站记住用户喜欢选择浏览哪类新闻. 在用户允许的情况下,还可以存储用户的登录信息,使得用户在访问网站时不必每次都键入这些信息 使用方法: 1.引入jquery.cookie.js <script src="scripts/jquery-1.6.4.js" type="text/javascript"></scrip

  • jQuery中cookie插件用法实例分析

    本文实例讲述了jQuery中cookie插件用法.分享给大家供大家参考,具体如下: Jquery里面提供了很多插件,方便,安全,快速实用.这节一起熟悉下JQUERY中操作Cookie的插件,插件名称为jquery.cookie.js,可以去官方网站下载. 下载地址: http://plugins.jquery.com/project/cookie. 插件主要报告如下几个用法 1.创建Cookie 创建一个名称为username,值为 admin的cookie ,如下 复制代码 代码如下: $.c

  • 基于JQuery的cookie插件

    简单使用方法: 复制代码 代码如下: <html> <head> <title>JQuery-Cookie插件</title> <script type="text/javascript" src="jquery-1.4.js"></script> <script type="text/javascript" src="jquery.cookie.js&quo

  • 深入理解ThreadLocal工作原理及使用示例

    简介:本文已一个简要的代码示例介绍ThreadLocal类的基本使用方式,在此基础上结合图片阐述它的内部工作原理. 早在JDK1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序. 当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本. 从线程的角

  • Python同步遍历多个列表的示例

    Python的for循环十分灵活,使用for循环我们可以很轻松地遍历一个列表,例如: a_list = ['z', 'c', 1, 5, 'm'] for each in a_list: print(each) 运行结果: 但是,有时遍历一个列表并不能满足我们的需求,在一些特殊的场合,我们可能会需要遍历两个甚至多个列表,例如,有两个列表,第一个列表存放的是人物的姓名,第二个列表存放的是人物的年纪,他们之间的关系是对应的,这时候该怎么办呢? ①使用zip()函数 (推荐) name_list =

随机推荐