You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在浏览器扩展中存储用户密码?技术实现咨询

浏览器扩展存储用户凭证的实现方案

首先,你得先在扩展的manifest.json里声明storage权限,不然没法用Chrome的存储API,另外你代码里用到了tabs.update,所以tabs权限也得加上:

{
  "manifest_version": 3,
  // 其他必填配置(比如name、version等)
  "permissions": ["storage", "tabs"]
}

核心注意点:别存明文密码!

密码属于敏感数据,直接存明文风险极高,必须加密后再存储。这里用浏览器原生支持的Web Crypto API做AES-GCM加密,是安全可靠的方案。

实现加密存储逻辑

先写加密、解密的工具函数:

// 生成加密密钥
async function generateKey() {
  return window.crypto.subtle.generateKey(
    { name: "AES-GCM", length: 256 },
    true,
    ["encrypt", "decrypt"]
  );
}

// 加密数据
async function encryptData(data, key) {
  const encoder = new TextEncoder();
  const dataBytes = encoder.encode(data);
  const iv = window.crypto.getRandomValues(new Uint8Array(12)); // AES-GCM推荐12字节IV
  const encrypted = await window.crypto.subtle.encrypt(
    { name: "AES-GCM", iv: iv },
    key,
    dataBytes
  );
  // 把IV和加密后的数据转成Base64,方便存储
  return {
    iv: btoa(String.fromCharCode(...iv)),
    encryptedData: btoa(String.fromCharCode(...new Uint8Array(encrypted)))
  };
}

// 解密数据
async function decryptData(encryptedObj, key) {
  const iv = new Uint8Array(atob(encryptedObj.iv).split("").map(c => c.charCodeAt(0)));
  const encryptedData = new Uint8Array(atob(encryptedObj.encryptedData).split("").map(c => c.charCodeAt(0)));
  const decrypted = await window.crypto.subtle.decrypt(
    { name: "AES-GCM", iv: iv },
    key,
    encryptedData
  );
  const decoder = new TextDecoder();
  return decoder.decode(decrypted);
}

修改现有代码,加入存储逻辑

当用户输入正确密码后,加密并存储到Chrome本地存储(chrome.storage.local,如果需要同步到用户Chrome账号,改用chrome.storage.sync):

button.addEventListener("click", async function () {
  let inputVal = document.getElementById("input").value;
  const correctPassword = "ramo";
  
  if (inputVal === correctPassword) {
    text.style.display = "none";
    chrome.tabs.update({ url: "https://www.youtube.com" });

    // 加密并存储密码
    const key = await generateKey();
    // 把密钥转成可存储的Base64格式
    const exportedKey = await window.crypto.subtle.exportKey("raw", key);
    const keyBase64 = btoa(String.fromCharCode(...new Uint8Array(exportedKey)));
    
    const encryptedObj = await encryptData(correctPassword, key);
    // 存储密钥和加密后的密码
    await chrome.storage.local.set({
      encryptedPassword: encryptedObj,
      encryptionKey: keyBase64
    });
  } else {
    toggleText();
  }
});

后续验证逻辑:读取存储的凭证

下次用户打开扩展时,先读取存储的加密数据,解密后和用户输入比对,避免重复输入:

// 页面加载时检查是否已存储凭证
async function checkStoredCredentials() {
  const storedData = await chrome.storage.local.get(["encryptedPassword", "encryptionKey"]);
  if (storedData.encryptedPassword && storedData.encryptionKey) {
    // 导入密钥
    const keyBytes = new Uint8Array(atob(storedData.encryptionKey).split("").map(c => c.charCodeAt(0)));
    const key = await window.crypto.subtle.importKey(
      "raw",
      keyBytes,
      { name: "AES-GCM", length: 256 },
      true,
      ["encrypt", "decrypt"]
    );
    // 解密密码
    const decryptedPassword = await decryptData(storedData.encryptedPassword, key);
    // 自动填充输入框,或直接用解密后的密码做验证
    document.getElementById("input").value = decryptedPassword;
  }
}

// 页面加载时调用
document.addEventListener("DOMContentLoaded", checkStoredCredentials);

额外提醒

  • 如果是存储用户自定义密码(不是固定的"ramo"),逻辑完全一致:先验证输入合法性,再加密存储
  • chrome.storage.local的数据隔离在扩展沙箱内,比普通localStorage更安全,但加密步骤不能省,防止扩展被攻破后数据泄露
  • 跨设备同步凭证用chrome.storage.sync,但注意该存储有容量限制(单扩展最多100KB)

内容的提问来源于stack exchange,提问作者Sao Petrik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 16:50:45