欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

同步cookie插件原理及實(shí)現(xiàn)示例

 更新時(shí)間:2022年10月27日 17:04:42   作者:WujieLi  
這篇文章主要為大家介紹了同步cookie插件原理及實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

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

因?yàn)槲覀児窘y(tǒng)一登錄、統(tǒng)一認(rèn)證體系實(shí)現(xiàn)方式是通過在公司域名下的 cookie 注入 acces_token 等內(nèi)容,然后在不同系統(tǒng)間通過攜帶的 cookie 信息進(jìn)行認(rèn)證并跳轉(zhuǎn)到對(duì)應(yīng)系統(tǒng)。

因?yàn)楸镜亻_發(fā)環(huán)境 localhost 和公司域名不在同一個(gè)域下,導(dǎo)致需要模擬登錄后,需要手動(dòng)將相關(guān) cookie 信息拷貝在 main.js 文件中,注入到 localhost 域名下。這就導(dǎo)致每次換一個(gè)用戶登錄,我就要手動(dòng)復(fù)制下面這些內(nèi)容,而且當(dāng) cookie 過期時(shí)也要重復(fù)一遍這樣的操作,這對(duì)一個(gè)程序員來說太繁瑣了,太麻煩了,嚴(yán)重影響了摸魚時(shí)間

// 每次在開發(fā)環(huán)境都要手動(dòng)復(fù)制 4 個(gè) 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'
}

所以在這樣一個(gè)背景下,我開始探索有什么辦法能不用每次都手動(dòng)復(fù)制這 4 個(gè)復(fù)制 cookie 的方案

最初想到的方案是直接通過獲取公司域名下的 cookie 信息,但因?yàn)闉g覽器的安全性質(zhì),是不能獲取跨域的 cookie 信息的,這個(gè)時(shí)候又想到改造瀏覽器的安全限制,但這個(gè)方案不具有通用性,就先放棄了。第二個(gè)考慮的方案是本地起一個(gè) node 中間件,通過這個(gè)中間間實(shí)現(xiàn)攜帶 cookie,但是因?yàn)閷?shí)現(xiàn)復(fù)雜也放棄了

之后在一次偶然的百度中發(fā)現(xiàn) chrome 插件可以突破跨域的限制,獲取到不同域名下的 cookie,然后百度了一下 chrome 插件的開發(fā)者文檔,找到了監(jiān)聽 cookie 變化的事件,研究到這里,我覺得可以開始實(shí)現(xiàn)需求了

擼起袖子開始干

一個(gè) chrome 插件本質(zhì)也是一個(gè)前端應(yīng)用運(yùn)行在 chrome 瀏覽器的環(huán)境里,所以直接就選擇了 Vue3 + Vite2 進(jìn)行開發(fā)。先用 pnpm create vite 初始化一個(gè) vite 項(xiàng)目,安裝好需要使用的 UI 庫 Ant Design Vue,刪掉無用的內(nèi)容之后先得到一個(gè)基礎(chǔ)的項(xiàng)目結(jié)構(gòu)

接下來配置 chrome 插件的信息,chrome 插件主要是在 manifest.json 文件中配置基礎(chǔ)信息。在 public 目錄下新建一個(gè) manifast.json 文件,文件中有幾個(gè)配置是比較重要的,這里特別解釋一下

manifest_version:定義配置清單的版本,從 Chrome 88 開始就是 V3,我是用的也是 3 這個(gè)版本

permissions:申請(qǐng)操作 chrome 的一些操作權(quán)限,這個(gè)插件里我主要用到的是 storage 和 cookies 的權(quán)限

host_permissions:申請(qǐng)有權(quán)限操作的域名,這里直接指定所有域名 "<all_urls>" 即可

background:后臺(tái)運(yùn)行腳本指定的屬性,可以是 HTML,也可以是 JS 文件,主要是用于在后臺(tái)監(jiān)聽 cookie 變化

插件的 icon 我是在阿里的 iconfont 上下載的,下載時(shí)可以選擇不同的大小,其他信息就直接附上源碼好了

{
  "manifest_version": 3,
  "name": "sync-cookie-extension",
  "version": "1.0.0",
  "description": "開發(fā)環(huán)境同步測(cè)試 cookie 至 localhost,便于本地請(qǐng)求服務(wù)攜帶 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": "解決本地開發(fā) localhost 請(qǐng)求無法攜帶 cookie 問題",
    "default_popup": "index.html"
  },
  "permissions": ["storage", "cookies"],
  "host_permissions": ["<all_urls>"],
  "background": {
    "service_worker": "background.js",
    "type": "module"
  }
}

然后就是插件的功能開發(fā),根據(jù)需求這個(gè)插件主要實(shí)現(xiàn)的兩個(gè)功能

  • 支持配置需要同步到本地的域名和 cookie 名稱,支持開啟和關(guān)閉同步
  • 當(dāng)配置列表中的 cookie 發(fā)生變化時(shí),能夠?qū)⑼街帘镜?/li>

第一個(gè)功能就是基于可編輯表格的 CRUD 一套功能,我是用的 Ant Design Vue 來開發(fā)的,一套操作下來頁面效果是這樣的(源碼地址

下面就是實(shí)現(xiàn)最主要的同步功能:當(dāng) from 字段下 cookie name 發(fā)上變化時(shí),將 cookie 同步至 to 字段對(duì)應(yīng)的域名下(默認(rèn)是 localhost )

第一步先要將我們?cè)诹斜碇信渲玫挠蛎畔⒋鎯?chǔ)在 localstorage 中,一方面為了在插件后臺(tái)中能夠獲取到需要同步的列表,另一方面當(dāng)插件刷新時(shí)列表信息也不會(huì)丟失。然后還要寫一個(gè)同步 cookie 的方法 updateCookie 方法用于加載時(shí)第一次同步 cookie

// 在 useStorage.ts 中定義存儲(chǔ) localstorage 方法和更新 cookie 的方法
import { ICookieTableDataSource, ICookie, TCookieConfig, LIST_KEY } from "../type";
// 增加協(xié)議頭
function addProtocol(uri: string) {
  return uri.startsWith("http") ? uri : `http://${uri}`;
}
// 移除協(xié)議頭
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;

第二步就是在插件首次加載的時(shí)候,從 localhost 讀取是否開啟同步和配置列表,然后讀取配置列表的信息更新 cookie

// 讀取是否同步開啟和配置列表
const dataSource = ref<ICookieTableDataSource[]>(DEFAULT_LIST); // DEFAULT_LIST 是默認(rèn)最初的同步列表,這樣第一次加載插件時(shí) localstorage 為空的話也不用手動(dòng)在寫一遍
const { updateStorage, getStorage, updateCookie } = useStorage();
onMounted(async () => {
  // 初始化開啟同步狀態(tài)
  const openSyncLocal = await getStorage("isOpenSync");
  if (!isEmpty(openSyncLocal)) {
    isOpenSync.value = openSyncLocal.isOpenSync;
  }
  // 從 localStorage 初始化數(shù)據(jù)
  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,
      });
    });
  }
});

第三步當(dāng)是否開啟同步狀態(tài)和配置列表發(fā)生變化時(shí)需要更新 localhost,這里使用 watch 監(jiān)聽同步狀態(tài)的改變,然后再保存同步列表的方法里新增更新 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);
}

到這里已經(jīng)實(shí)現(xiàn)的第一次的 cookie 同步功能,然后就要用到監(jiān)聽 cookie 變化的事件 chrome.cookies.onChanged.addListener 了。我們之前在 manifest.json 文件中配置了 background 這個(gè)參數(shù),這個(gè)時(shí)候就要用上了

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

在項(xiàng)目 public 目錄下新建 background.js,添加 cookie 改變監(jiān)聽事件函數(shù),然后從 localhost 中獲取是否開啟同步狀態(tài)和配置列表,在開啟同步的狀態(tài)下,從列表中找到需要更新的 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,
  });
}
// 增加協(xié)議頭
function addProtocol(uri) {
  return uri.startsWith("http") ? uri : `http://${uri}`;
}
// 移除協(xié)議頭
function removeProtocol(uri) {
  return uri.startsWith("http")
    ? uri.replace("http://", "").replace("https://", "")
    : uri;
}
function equalDomain(domain1, domain2) {
  return addProtocol(domain1) === addProtocol(domain2);
}

到這里同步功能就已經(jīng)實(shí)現(xiàn)了,接下來打包項(xiàng)目 pnpm run build,打開 chrome 瀏覽器開發(fā)者模式,選擇“加載解壓縮的擴(kuò)展”,選擇打包的 dist 文件安裝,如果安裝成功的話可以看到這樣一個(gè)圖標(biāo)

最后測(cè)試一下插件的效果,在百度域名下輸入一個(gè)測(cè)試域名,然后在 localhost 下刷新一下,可以看到 cookie 已經(jīng)成功同步過去了,大功告成

代碼我也上傳到了 github,有興趣的話大家也可以 star 支持一波,源碼地址

以上就是同步cookie插件原理及實(shí)現(xiàn)示例的詳細(xì)內(nèi)容,更多關(guān)于同步cookie插件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue 實(shí)現(xiàn)監(jiān)聽窗口關(guān)閉事件,并在窗口關(guān)閉前發(fā)送請(qǐng)求

    Vue 實(shí)現(xiàn)監(jiān)聽窗口關(guān)閉事件,并在窗口關(guān)閉前發(fā)送請(qǐng)求

    這篇文章主要介紹了Vue 實(shí)現(xiàn)監(jiān)聽窗口關(guān)閉事件,并在窗口關(guān)閉前發(fā)送請(qǐng)求,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • vue 自定義右鍵樣式的實(shí)例代碼

    vue 自定義右鍵樣式的實(shí)例代碼

    這篇文章主要介紹了vue 自定義右鍵樣式的實(shí)例代碼,代碼簡單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-11-11
  • vue+iview寫個(gè)彈框的示例代碼

    vue+iview寫個(gè)彈框的示例代碼

    本篇文章主要介紹了vue+iview寫個(gè)彈框的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • vue項(xiàng)目打包并部署到Linux服務(wù)器的詳細(xì)過程

    vue項(xiàng)目打包并部署到Linux服務(wù)器的詳細(xì)過程

    我們?cè)跁?huì)開發(fā)項(xiàng)目的同時(shí),也應(yīng)該了解一下項(xiàng)目是如何部署到服務(wù)器的,下面這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目打包并部署到Linux服務(wù)器的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • vue項(xiàng)目中axios使用詳解

    vue項(xiàng)目中axios使用詳解

    這篇文章主要介紹了vue項(xiàng)目中axios使用方法以及原理介紹,如果你正巧學(xué)習(xí)這個(gè)知識(shí)點(diǎn),那么參考下吧。
    2018-02-02
  • Vue自定義依賴引入的最佳實(shí)踐記錄

    Vue自定義依賴引入的最佳實(shí)踐記錄

    在現(xiàn)代前端開發(fā)中,自定義引入依賴是提升開發(fā)效率的關(guān)鍵,unplugin-auto-import插件可以幫助開發(fā)者自動(dòng)引入JS模塊,包括本地編寫的工具方法和第三方庫,通過簡單的配置,開發(fā)者可以實(shí)現(xiàn)Vue基本庫、本地文件以及第三方插件的自動(dòng)引入
    2024-10-10
  • 前端項(xiàng)目中如何使用百度地圖api(含實(shí)例)

    前端項(xiàng)目中如何使用百度地圖api(含實(shí)例)

    當(dāng)我們遇到定位展示的時(shí)候會(huì)出現(xiàn)使用地圖展示的需求,下面這篇文章主要給大家介紹了關(guān)于前端項(xiàng)目中如何使用百度地圖api(含實(shí)例)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • 一次前端Vue項(xiàng)目國際化解決方案的實(shí)戰(zhàn)記錄

    一次前端Vue項(xiàng)目國際化解決方案的實(shí)戰(zhàn)記錄

    這篇文章主要給大家介紹了關(guān)于前端Vue項(xiàng)目國際化解決方案的實(shí)戰(zhàn)記錄,以上只是一部分Vue項(xiàng)目開發(fā)中遇到的典型問題和解決方案,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-07-07
  • Vue 2.5 Level E 發(fā)布了: 新功能特性一覽

    Vue 2.5 Level E 發(fā)布了: 新功能特性一覽

    很高興Vue 2.5 Level E 發(fā)布了。在這篇文章中,我們將重點(diǎn)介紹一些更重要的的變化:更好的 TypeScript 集成,更好的錯(cuò)誤處理,更好地支持單文件組件中的函數(shù)式組件以及與環(huán)境無關(guān)的服務(wù)端渲染
    2017-10-10
  • vue項(xiàng)目中使用window的onresize事件方式

    vue項(xiàng)目中使用window的onresize事件方式

    這篇文章主要介紹了vue項(xiàng)目中使用window的onresize事件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08

最新評(píng)論