Cookie Switch: 多账号快速切换的 Chrome 插件
一、简介
Cookie Switch 是一个 Chrome 插件,为了解决同一浏览器中多个账号快速切换登录态的问题。
二、起因
日常测试工作中,经常需要在多个账号之间来回切换,属于没什么意义的重复性劳动,反复登录退出账号实在效率低。
需要反复登录退出账号的原因在于浏览器只保存一个登录态,无法多账号并存,因此本插件通过直接管理 cookie 来实现快速即时的账号切换。
三、整体架构
四、核心功能实现
1.测试环境账号登录流程
登录流程分为三步:获取验证码 → 获取加密密钥 → 提交登录。
为什么需要这些步骤:
产品的登录接口需要先获取 RSA 公钥对密码加密,同时需要验证码 token。所以登录不是一个简单的 POST,需要模仿真实的调用过程。
preLogin 函数 — 获取验证码和加密密钥:
async function preLogin(uname) {
let hash = "", key = "", token = "";
// 1. 获取验证码 token 和图片
const captchaResp = await $.ajax({
url: "http://xxx.com/captcha",
method: "GET",
});
token = captchaResp.data.token;
const imgURL = "http://xxx.com/recaptcha/img?token=" + token;
showPass(imgURL); // 弹出验证码输入框
// 2. 获取 RSA 加密的公钥和 hash
const keyResp = await $.ajax({
url: "http://xxx.com/key?_=" + Date.now(),
method: "GET",
});
hash = keyResp.data.hash;
key = keyResp.data.key;
return { hash, key, token, uname };
}login 函数 — RSA 加密后提交:
async function login(options) {
const { uname, pwd, key, hash, token, captcha } = options;
// RSA 加密密码: result = encrypt(hash + pwd)
var n = new JSEncrypt;
n.setPublicKey(key);
var result = n.encrypt(hash + pwd);
var response = await $.ajax({
url: "https://xxx.com/web/login",
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
data: {
source: "xxx",
username: uname,
password: result,
captcha: captcha,
token: token
}
});
if (response.code == 0) {
return Promise.resolve(response.message);
} else {
return Promise.reject(response.message);
}
}登录成功后的调用流程:
// 输入验证码后回车
$("#captcha-input").on('keyup', async function (e) {
if (e.key === 'Enter') {
loginInfo['pwd'] = $("#pwd-input").val();
loginInfo['captcha'] = $(this).val();
login(loginInfo).then(async () => {
// 1. 保存当前 cookie 到账号
saveCurrCookieToAccount(loginInfo['uname']);
// 2. 获取用户信息(mid)
let uInfo = await uatUserserInfo();
await addOrUpdateAccount(loginInfo['uname'], uInfo.mid);
// 3. 刷新页面
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.reload(tabs[0].id);
});
});
}
});2.Cookie 管理:两个独立的存储体系
插件管理几个关键 cookie:SESSDATA(登录会话)、DedeUserID(用户 ID)。
账号存储 (state-storage.js):
保存的结构是 Accounts 数组,每个账号包含 { uname, mid, cookies[] }。登录后自动关联 cookie,点击账号行即可切换。
自定义 Cookie 保存 (custom-storage.js):
用于线上环境,点击保存按钮即可抓取当前 tab 的 cookie 并存储。切换时先删后写,保证 cookie 写入成功。
切换 cookie 的核心逻辑:
async function setCookieFromAccount(uname) {
const idx = Accounts.findIndex(account => account.uname === uname);
if (idx === -1) return;
// 先删除当前所有 cookie
await deleteCookies();
// 逐一写入目标账号的 cookie
let cookies = Accounts[idx].cookies;
let promises = cookies.map(cookie => {
let domain = stripLeadingDot(cookie.domain);
let url = toURL(domain, cookie.path, cookie.secure);
cookie.url = url;
delete cookie.hostOnly;
delete cookie.session;
return chrome.cookies.set(cookie);
});
await Promise.all(promises);
}
async function deleteCookies() {
// 删除 cookie(http 和 https 各删一次)
const cookies = ["SESSDATA", "DedeUserID"];
for (let name of cookies) {
await chrome.cookies.remove({ name, url: "https://.xxx.com/" });
await chrome.cookies.remove({ name, url: "http://.xxx.com/" });
}
}3.请求头修改:Declarative Net Request
为什么需要这个功能:
页面有跨域校验,登录请求的 Origin 和 Referer 必须设置为 https://www.bilibili.com。扩展通过 Manifest V3 的 declarativeNetRequest API 自动修改请求头,无需在代码中手动处理。
[
{
"id": 1,
"priority": 1,
"action": {
"type": "modifyHeaders",
"requestHeaders": [
{
"header": "Origin",
"operation": "set",
"value": "https://www.xxx.com"
},
{
"header": "Referer",
"operation": "set",
"value": "https://www.xxx.com/"
}
]
},
"condition": {
"urlFilter": "/web/login",
"resourceTypes": ["main_frame", "sub_frame", "xmlhttprequest"]
}
}
]4.登录态自动识别
打开弹窗时,扩展会通过 refreshActiveAccount() 自动识别当前 tab 的登录账号,并在 UI 上高亮显示。
async function refreshActiveAccount() {
// 获取当前 cookie 中的 SESSDATA
const currCookie = await getCurrentCookie();
const currSessionData = currCookie.find(c => c.name === 'SESSDATA')?.value;
// 遍历账号列表,匹配 SESSDATA
for (let account of uatAccounts) {
if (account.cookies.some(c => c.value === currSessionData)) {
activeAccount = account.uname;
break;
}
}
}五、总结
Cookie Switch 的核心设计理念是绕过重复登录,直接操作登录态凭证。通过 chrome.cookies API 实现 cookie 的保存和注入,覆盖了日常工作中多账号切换的主要场景。