浏览器插件 chrome.* API 全量速查大全

本手册按命名空间组织。每个命名空间一个 ## 主节,每个常用方法一个 ### 子节,配参数表与最小可运行示例。代码若运行在 Service Worker(背景脚本,下文简称 SW)、内容脚本(content script)、弹窗页(popup)或选项页(options),均在示例中标注上下文。 下表用于快速判断某 API 需要在 manifest.json 声明哪些权限,以及可在哪些上下文调用。「SW」=Service Worker;「CS」=内容脚本;「页面」=popup/options/sidePanel 等扩展页。 全上下文可用,无需任何权限,是消

分享

官方文档:https://developer.chrome.com/docs/extensions/reference/api
适用版本:Manifest V3 / Chrome 138+
核实日期:2026-06-06
本篇为系列「API 参考篇」。所有 chrome.* 命名空间方法在 MV3 下默认返回 Promise(同时仍兼容回调风格),本文示例一律采用 Promise 风格。

本手册按命名空间组织。每个命名空间一个 ## 主节,每个常用方法一个 ### 子节,配参数表与最小可运行示例。代码若运行在 Service Worker(背景脚本,下文简称 SW)、内容脚本(content script)、弹窗页(popup)或选项页(options),均在示例中标注上下文。

API 总览:权限与可用上下文

下表用于快速判断某 API 需要在 manifest.json 声明哪些权限,以及可在哪些上下文调用。「SW」=Service Worker;「CS」=内容脚本;「页面」=popup/options/sidePanel 等扩展页。

API 命名空间 所需 permission 可用上下文 备注
chrome.runtime SW / CS / 页面 全上下文可用,无需声明
chrome.tabs 无(读 url/title 需 tabs 或 host 权限) SW / 页面 CS 不可直接用
chrome.windows SW / 页面 同 tabs
chrome.storage storage SW / CS / 页面 四区共享 API
chrome.scripting scripting + host 权限 SW / 页面 注入目标需 host 权限
chrome.action 无(manifest 需 action 键) SW / 页面 工具栏图标
chrome.contextMenus contextMenus SW 右键菜单
chrome.alarms alarms SW 定时任务
chrome.commands 无(manifest 需 commands 键) SW 快捷键
chrome.notifications notifications SW / 页面 系统通知
chrome.sidePanel sidePanel SW / 页面 侧边栏,Chrome 114+
chrome.permissions SW / 页面 运行时申请 optional 权限
chrome.cookies cookies + host 权限 SW / 页面 读写 Cookie
chrome.webNavigation webNavigation SW 导航事件监听
chrome.declarativeNetRequest declarativeNetRequestdeclarativeNetRequestWithHostAccess SW 声明式拦截
chrome.identity identity SW / 页面 OAuth
chrome.offscreen offscreen SW 在 SW 中用 DOM
chrome.i18n 无(需 _locales/ SW / CS / 页面 国际化
chrome.downloads downloads SW / 页面 下载管理
chrome.bookmarks bookmarks SW / 页面 书签
chrome.history history SW / 页面 历史记录

chrome.runtime

全上下文可用,无需任何权限,是消息通信与生命周期管理的核心。

chrome.runtime.id

只读属性,返回当前扩展的 ID(32 位小写字母字符串)。可在 CS 中用于拼接 chrome-extension:// URL。

// 上下文:任意
console.log(chrome.runtime.id); // "abcdefghijklmnopabcdefghijklmnop"

chrome.runtime.getURL(path)

把扩展内的相对路径转换为完整的 chrome-extension://<id>/... 绝对 URL。常用于在 CS 中加载 web_accessible_resources 里声明的资源。

参数 类型 默认值 说明
path string 必填 相对扩展根目录的路径,前导 / 可选
// 上下文:内容脚本
const imgUrl = chrome.runtime.getURL("assets/logo.png");
const img = document.createElement("img");
img.src = imgUrl;
document.body.append(img);

// 错误:直接拼字符串,扩展 ID 改变后失效
// const bad = "chrome-extension://abcd.../assets/logo.png"; // 错误:硬编码 ID

chrome.runtime.getManifest()

同步返回解析后的 manifest.json 对象,无参数。用于读取版本号等。

// 上下文:任意
const { version, name } = chrome.runtime.getManifest();
console.log(`${name} v${version}`);

chrome.runtime.sendMessage(extensionId?, message, options?)

向扩展内其它上下文(SW、其它页面)发送一次性消息,返回 Promise 解析为接收方的响应。单条消息上限 64 MiB

参数 类型 默认值 说明
extensionId string 当前扩展 目标扩展 ID,发给自己可省略
message any 必填 任意 JSON 可序列化值
options object undefined includeTlsChannelId 等,少用
// 上下文:popup
const res = await chrome.runtime.sendMessage({ type: "getCount" });
console.log(res.count);

// 错误:消息含函数/DOM 节点,无法 JSON 序列化
// await chrome.runtime.sendMessage({ el: document.body }); // 错误:不可序列化

chrome.runtime.onMessage

监听 sendMessage 发来的消息。回调签名 (message, sender, sendResponse)异步回复必须 return true 以保持消息通道开放;或在 Chrome 148+ 直接返回 Promise。

回调参数 类型 说明
message any 发送方传入的消息体
sender MessageSender tabidurlorigin
sendResponse function 调用以回送响应,可异步调用
// 上下文:Service Worker
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg.type === "getCount") {
    chrome.storage.local.get("count").then(({ count }) => {
      sendResponse({ count: count ?? 0 });
    });
    return true; // 关键:异步回复需返回 true 保持通道
  }
  // 错误:async 监听器整体返回 Promise 在 148 前不被识别,回复丢失
});

chrome.runtime.connect(extensionId?, connectInfo?)

建立长连接,返回 Port 对象,适合高频或流式通信。

参数 类型 默认值 说明
extensionId string 当前扩展 目标扩展 ID
connectInfo object undefined { name } 命名通道,便于区分连接类型
// 上下文:popup
const port = chrome.runtime.connect({ name: "live-feed" });
port.postMessage({ subscribe: true });
port.onMessage.addListener((m) => console.log("推送:", m));
port.onDisconnect.addListener(() => console.log("通道关闭"));

chrome.runtime.onConnect

监听 connect 建立的连接,回调收到 Port

// 上下文:Service Worker
chrome.runtime.onConnect.addListener((port) => {
  if (port.name !== "live-feed") return;
  port.onMessage.addListener((m) => {
    if (m.subscribe) port.postMessage({ tick: Date.now() });
  });
});

chrome.runtime.onInstalled

扩展首次安装、更新或 Chrome 升级时触发。回调参数 details.reason 取值:"install"(首装)、"update"(更新)、"chrome_update"(浏览器升级)、"shared_module_update"(依赖模块更新)。

// 上下文:Service Worker
chrome.runtime.onInstalled.addListener((details) => {
  if (details.reason === "install") {
    chrome.storage.local.set({ count: 0 }); // 初始化默认配置
  } else if (details.reason === "update") {
    console.log("从", details.previousVersion, "升级");
  }
});

chrome.runtime.onStartup

用户启动 Chrome、加载该扩展的 profile 时触发一次。无参数。注意:扩展更新或安装时不会触发。

// 上下文:Service Worker
chrome.runtime.onStartup.addListener(() => {
  console.log("浏览器启动,SW 唤醒");
});

chrome.runtime.lastError

只读属性,仅在回调风格 API 出错时于回调内有值。Promise 风格用 try/catch 即可,一般不再需要它。

// 上下文:Service Worker(回调风格 API 仍存在的场景)
chrome.tabs.sendMessage(tabId, { ping: 1 }, () => {
  if (chrome.runtime.lastError) {
    console.warn("目标无监听器:", chrome.runtime.lastError.message);
  }
});

chrome.runtime.getContexts(filter)

Chrome 116+。查询当前扩展存活的所有上下文(SW、offscreen、popup、tab 等),返回 ExtensionContext[]

参数 类型 默认值 说明
filter object 必填 contextTypesdocumentUrlstabIds 等过滤字段

contextTypes 取值:"TAB""POPUP""BACKGROUND""OFFSCREEN_DOCUMENT""SIDE_PANEL""DEVELOPER_TOOLS"

// 上下文:Service Worker
const ctxs = await chrome.runtime.getContexts({
  contextTypes: ["OFFSCREEN_DOCUMENT"]
});
const hasOffscreen = ctxs.length > 0; // 判断 offscreen 是否已存在

chrome.tabs

无需权限即可调用,但读取 urltitlefavIconUrlpendingUrl 需要 tabs 权限或匹配该标签的 host 权限。不可在 CS 中直接使用。

chrome.tabs.query(queryInfo)

按条件查询标签页,返回 Tab[]

参数 类型 默认值 说明
queryInfo.active boolean 不限 是否为窗口内激活标签
queryInfo.currentWindow boolean 不限 是否在当前窗口
queryInfo.url string | string[] 不限 match pattern 过滤,需 host 权限
queryInfo.status string 不限 "loading""complete"
queryInfo.pinned boolean 不限 是否固定
// 上下文:Service Worker
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
console.log("当前标签:", tab.id, tab.url);

// 错误:不传任何条件会返回所有窗口所有标签,浪费
// const all = await chrome.tabs.query({}); // 错误:全表扫描

chrome.tabs.get(tabId)

按 ID 获取单个标签的最新信息。

参数 类型 默认值 说明
tabId number 必填 标签 ID
// 上下文:Service Worker
const tab = await chrome.tabs.get(123);

chrome.tabs.create(createProperties)

新建标签页,返回新建的 Tab

参数 类型 默认值 说明
url string 新标签页 目标 URL,扩展页用 chrome.runtime.getURL
active boolean true 是否前台激活
index number 末尾 在窗口中的位置
windowId number 当前窗口 目标窗口 ID
pinned boolean false 是否固定
// 上下文:Service Worker
await chrome.tabs.create({ url: chrome.runtime.getURL("options.html") });

chrome.tabs.update(tabId?, updateProperties)

修改标签属性(导航、激活、静音等)。

参数 类型 默认值 说明
tabId number 当前激活标签 省略则作用于激活标签
updateProperties.url string 不变 导航到新 URL
updateProperties.active boolean 不变 激活该标签
updateProperties.muted boolean 不变 静音/取消静音
updateProperties.pinned boolean 不变 固定/取消固定
// 上下文:Service Worker
await chrome.tabs.update(tabId, { url: "https://example.com", active: true });

chrome.tabs.remove(tabIds)

关闭一个或多个标签。

参数 类型 默认值 说明
tabIds number | number[] 必填 单个或数组
// 上下文:Service Worker
await chrome.tabs.remove([101, 102]); // 批量关闭

chrome.tabs.sendMessage(tabId, message, options?)

向指定标签内的内容脚本发送消息,返回 Promise 解析为 CS 的响应。

参数 类型 默认值 说明
tabId number 必填 目标标签
message any 必填 JSON 可序列化值
options.frameId number 所有 frame 仅发给指定子框架
// 上下文:Service Worker
try {
  const res = await chrome.tabs.sendMessage(tabId, { type: "highlight" });
} catch (e) {
  // 该标签无内容脚本监听时抛错,需捕获
  console.warn("无 CS 接收:", e.message);
}

chrome.tabs.captureVisibleTab(windowId?, options?)

截取指定窗口当前可见标签的画面,返回 data URL。需要 activeTab<all_urls> host 权限。

参数 类型 默认值 说明
windowId number 当前窗口 目标窗口 ID
options.format string "jpeg" "jpeg""png"
options.quality number 由格式定 0-100,仅 jpeg 有效
// 上下文:Service Worker(需 activeTab 权限)
const dataUrl = await chrome.tabs.captureVisibleTab(undefined, {
  format: "png"
});

chrome.tabs.group(options)

将标签加入标签组,返回 groupId

参数 类型 默认值 说明
options.tabIds number | number[] 必填 要分组的标签
options.groupId number 新建组 加入已有组的 ID
options.createProperties.windowId number 当前窗口 新组所在窗口
// 上下文:Service Worker
const groupId = await chrome.tabs.group({ tabIds: [101, 102] });
await chrome.tabGroups.update(groupId, { title: "工作", color: "blue" });

chrome.tabs.onUpdated

标签更新(URL、加载状态、标题等变化)时触发。回调 (tabId, changeInfo, tab)

// 上下文:Service Worker
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (changeInfo.status === "complete" && tab.url?.startsWith("https://")) {
    console.log("页面加载完成:", tab.url);
  }
});

chrome.tabs.onActivated

用户切换激活标签时触发。回调 activeInfotabIdwindowId

// 上下文:Service Worker
chrome.tabs.onActivated.addListener(({ tabId }) => {
  console.log("切换到标签", tabId);
});

chrome.tabs.onRemoved

标签关闭时触发。回调 (tabId, removeInfo)removeInfo.isWindowClosing 表示是否因窗口关闭。

// 上下文:Service Worker
chrome.tabs.onRemoved.addListener((tabId, info) => {
  console.log("关闭标签", tabId, "窗口关闭:", info.isWindowClosing);
});

chrome.windows

操作浏览器窗口,无需权限。

chrome.windows.create(createData)

新建窗口,返回 Window

参数 类型 默认值 说明
url string | string[] 新标签页 初始打开的 URL
type string "normal" "normal" / "popup" / "panel"
state string "normal" "normal" / "minimized" / "maximized" / "fullscreen"
focused boolean true 是否获取焦点
width / height number 自动 像素尺寸
left / top number 自动 屏幕位置
incognito boolean false 是否隐身窗口
// 上下文:Service Worker
await chrome.windows.create({
  url: chrome.runtime.getURL("panel.html"),
  type: "popup",
  width: 400,
  height: 600
});

chrome.windows.get(windowId, queryOptions?)

获取指定窗口。queryOptions.populatetrue 时附带 tabs 数组。

参数 类型 默认值 说明
windowId number 必填 窗口 ID
queryOptions.populate boolean false 是否包含标签列表
// 上下文:Service Worker
const win = await chrome.windows.get(winId, { populate: true });
console.log("窗口含标签数:", win.tabs.length);

chrome.windows.getAll(queryOptions?)

返回所有窗口数组。

// 上下文:Service Worker
const wins = await chrome.windows.getAll({ populate: false });

chrome.windows.update(windowId, updateInfo)

修改窗口状态、位置、尺寸。

参数 类型 默认值 说明
windowId number 必填 窗口 ID
updateInfo.focused boolean 不变 置顶聚焦
updateInfo.state string 不变 同 create 的 state
updateInfo.drawAttention boolean 不变 任务栏闪烁提醒
// 上下文:Service Worker
await chrome.windows.update(winId, { focused: true, state: "maximized" });

chrome.windows.remove(windowId)

关闭指定窗口。

// 上下文:Service Worker
await chrome.windows.remove(winId);

chrome.storage

storage 权限。四个存储区共享同一套方法 API。所有值必须 JSON 可序列化。

四区配额对比

总配额 单项上限 最大项数 写频率限制 同步 上下文
local 10 MB SW/CS/页面
sync 100 KB(102,400 字节) 8 KB(8,192 字节) 512 120 次/分、1,800 次/小时 跨设备 SW/CS/页面
session 10 MB 否(内存,重启清空) 默认仅 SW,可放开
managed 只读 由策略下发 SW/CS/页面

local 在 Chrome 113 及更早为 5 MB;session 在 Chrome 111 及更早为 1 MB。managed 由企业策略 JSON 提供,扩展只读。

get(keys?)

读取一个或多个键,返回对象。keysnull 或省略时读取整个区。

参数 类型 默认值 说明
keys string | string[] | object | null null 传对象时其值作为缺省返回值
// 上下文:任意
const { theme = "light" } = await chrome.storage.local.get({ theme: "light" });
const multi = await chrome.storage.sync.get(["a", "b"]);

set(items)

写入键值对,整体覆盖同名键。

参数 类型 默认值 说明
items object 必填 一次写多个键,减少写次数
// 上下文:任意
await chrome.storage.local.set({ count: 5, theme: "dark" });

// 错误:循环里逐条 set,撞 sync 写频率上限
// for (const k in data) await chrome.storage.sync.set({ [k]: data[k] }); // 错误:高频写

remove(keys)

删除指定键。

参数 类型 默认值 说明
keys string | string[] 必填 要删除的键
// 上下文:任意
await chrome.storage.local.remove(["count", "theme"]);

clear()

清空整个存储区,无参数。

// 上下文:任意
await chrome.storage.session.clear();

getBytesInUse(keys?)

返回指定键(或整区)占用的字节数。sync 区按此判断是否接近配额。

参数 类型 默认值 说明
keys string | string[] | null null 省略统计整区
// 上下文:任意
const used = await chrome.storage.sync.getBytesInUse(null);
console.log(`已用 ${used}/102400 字节`);

setAccessLevel(accessOptions)

控制存储区能否被不可信上下文(如 MAIN world 注入脚本)访问。主要用于 session 区。

参数 类型 默认值 说明
accessOptions.accessLevel string "TRUSTED_CONTEXTS" 访问级别枚举

accessLevel 取值:"TRUSTED_CONTEXTS"(仅扩展自身上下文,默认)、"TRUSTED_AND_UNTRUSTED_CONTEXTS"(含内容脚本等外部上下文)。

// 上下文:Service Worker
// 允许内容脚本读写 session 区
await chrome.storage.session.setAccessLevel({
  accessLevel: "TRUSTED_AND_UNTRUSTED_CONTEXTS"
});

onChanged

任意键变化时触发。storage.onChanged 监听所有区;各区也有自身 onChanged。回调 (changes, areaName)changes{ key: { oldValue, newValue } }

// 上下文:任意
chrome.storage.onChanged.addListener((changes, area) => {
  if (area === "local" && changes.theme) {
    console.log("主题从", changes.theme.oldValue, "变为", changes.theme.newValue);
  }
});

chrome.scripting

scripting 权限,注入目标还需对应 host 权限(或 activeTab)。仅可在 SW 与扩展页调用。

executeScript(injection)

向目标注入 JS 函数或文件,返回 InjectionResult[]

参数 类型 默认值 说明
injection.target object 必填 { tabId, frameIds?, allFrames? }
injection.func function 要执行的函数(与 files 二选一)
injection.args any[] [] 传给 func 的参数,须可序列化
injection.files string[] 要注入的脚本文件路径
injection.world string "ISOLATED" 执行环境,见下
injection.injectImmediately boolean false 尽早注入而不等导航稳定

world 取值:"ISOLATED"(扩展专属隔离环境,与页面共享 DOM 但 JS 变量隔离,默认)、"MAIN"(页面主世界,与网页脚本共享 window,可访问页面变量但无 chrome.* 高权 API)。

// 上下文:Service Worker
const [result] = await chrome.scripting.executeScript({
  target: { tabId },
  func: (prefix) => prefix + document.title, // 函数体在目标页运行
  args: ["标题:"]
});
console.log(result.result);

// MAIN world 读取页面全局变量
await chrome.scripting.executeScript({
  target: { tabId },
  world: "MAIN",
  func: () => window.__APP_STATE__
});

// 错误:func 引用了 SW 作用域的外部变量(闭包不跨进程)
// const x = 1; executeScript({ target, func: () => x }); // 错误:func 内 x 未定义

insertCSS(injection)

注入样式表,返回 Promise<void>

参数 类型 默认值 说明
injection.target object 必填 { tabId, frameIds?, allFrames? }
injection.css string CSS 字符串(与 files 二选一)
injection.files string[] CSS 文件路径
injection.origin string "AUTHOR" "AUTHOR""USER"(优先级不同)
// 上下文:Service Worker
await chrome.scripting.insertCSS({
  target: { tabId },
  css: "body { filter: invert(1); }"
});

removeCSS(injection)

移除此前用 insertCSS 注入的样式,参数须与注入时一致。

// 上下文:Service Worker
await chrome.scripting.removeCSS({
  target: { tabId },
  css: "body { filter: invert(1); }" // 须与 insert 时完全相同
});

registerContentScripts(scripts)

动态注册内容脚本(无需写在 manifest),返回 Promise<void>

参数(每项) 类型 默认值 说明
id string 必填 唯一标识,不能以 _ 开头
matches string[] 必填 match pattern
js / css string[] 脚本/样式文件
runAt string "document_idle" "document_start" / "document_end" / "document_idle"
world string "ISOLATED" 同 executeScript
persistAcrossSessions boolean true 浏览器重启后是否保留
allFrames boolean false 是否注入所有子框架
// 上下文:Service Worker
await chrome.scripting.registerContentScripts([{
  id: "auto-cs",
  matches: ["https://example.com/*"],
  js: ["injected.js"],
  runAt: "document_idle"
}]);

updateContentScripts(scripts)

id 更新已注册脚本的字段,返回 Promise<void>

// 上下文:Service Worker
await chrome.scripting.updateContentScripts([{
  id: "auto-cs",
  matches: ["https://example.com/*", "https://example.org/*"]
}]);

unregisterContentScripts(filter?)

注销动态脚本。省略 filter 注销全部。

参数 类型 默认值 说明
filter.ids string[] 全部 要注销的脚本 ID
// 上下文:Service Worker
await chrome.scripting.unregisterContentScripts({ ids: ["auto-cs"] });

getRegisteredContentScripts(filter?)

返回已注册的动态脚本列表。

// 上下文:Service Worker
const scripts = await chrome.scripting.getRegisteredContentScripts();
console.log("已注册数量:", scripts.length);

chrome.action

manifest 需声明 action 键。无需 permission。控制工具栏图标。

setBadgeText(details)

设置图标角标文字(最多约 4 字符可见)。

参数 类型 默认值 说明
details.text string "" 角标文本,空串清除
details.tabId number 全局 仅对指定标签生效
// 上下文:Service Worker
await chrome.action.setBadgeText({ text: "5", tabId });

setBadgeBackgroundColor(details)

设置角标背景色。

参数 类型 默认值 说明
details.color string | number[] "#FF0000"[255,0,0,255]
details.tabId number 全局 限定标签
// 上下文:Service Worker
await chrome.action.setBadgeBackgroundColor({ color: "#D32F2F" });

setIcon(details)

动态切换图标,返回 Promise<void>

参数 类型 默认值 说明
details.path string | object { "16": "...", "32": "..." } 多尺寸
details.imageData ImageData | object 由 OffscreenCanvas 生成的位图
details.tabId number 全局 限定标签
// 上下文:Service Worker
await chrome.action.setIcon({ path: { 16: "on16.png", 32: "on32.png" } });

setPopup(details)

设置点击图标时弹出的 HTML。设为 "" 则恢复触发 onClicked

参数 类型 默认值 说明
details.popup string popup 页路径,空串禁用 popup
details.tabId number 全局 限定标签
// 上下文:Service Worker
await chrome.action.setPopup({ popup: "popup.html" });

setTitle(details)

设置图标悬停提示。

// 上下文:Service Worker
await chrome.action.setTitle({ title: "未读 5 条" });

enable(tabId?) / disable(tabId?)

启用/禁用图标点击。禁用后图标变灰。

// 上下文:Service Worker
await chrome.action.disable(tabId);
await chrome.action.enable(tabId);

onClicked

仅当未设置 popup 时,点击图标触发。回调收到当前 Tab

// 上下文:Service Worker
chrome.action.onClicked.addListener((tab) => {
  console.log("点击图标,当前页:", tab.url);
});

chrome.contextMenus

contextMenus 权限。仅在 SW 中创建。

create(createProperties, callback?)

创建右键菜单项,同步返回菜单 ID。应在 onInstalled 中创建,避免重复。

参数 类型 默认值 说明
id string 自动 菜单项唯一 ID
title string 必填(除分隔符外) 显示文字,%s 表示选中文本
contexts string[] ["page"] "page"/"selection"/"link"/"image"/"editable"/"action"
type string "normal" "normal"/"checkbox"/"radio"/"separator"
parentId string 父菜单 ID,构建子菜单
documentUrlPatterns string[] 不限 仅在匹配页面显示
// 上下文:Service Worker
chrome.runtime.onInstalled.addListener(() => {
  chrome.contextMenus.create({
    id: "search-sel",
    title: '搜索 "%s"',
    contexts: ["selection"]
  });
});

update(id, updateProperties)

修改已有菜单项。

// 上下文:Service Worker
await chrome.contextMenus.update("search-sel", { title: "已禁用", enabled: false });

remove(menuItemId) / removeAll()

删除单个或全部菜单项。

// 上下文:Service Worker
await chrome.contextMenus.remove("search-sel");
await chrome.contextMenus.removeAll();

onClicked

菜单项被点击时触发。回调 (info, tab)infomenuItemIdselectionTextlinkUrlchecked 等。

// 上下文:Service Worker
chrome.contextMenus.onClicked.addListener((info, tab) => {
  if (info.menuItemId === "search-sel") {
    chrome.tabs.create({
      url: "https://www.google.com/search?q=" + encodeURIComponent(info.selectionText)
    });
  }
});

chrome.alarms

alarms 权限。MV3 中替代 setTimeout/setInterval(SW 随时可能休眠)。

最小周期:Chrome 120 起从 1 分钟降为 30 秒periodInMinutes: 0.5)。已打包扩展中小于 0.5 的值不被采纳并产生警告;未打包扩展无此限制。Chrome 117 起最多 500 个活动 alarm。

create(name?, alarmInfo)

创建定时器,返回 Promise<void>。同名 alarm 会被覆盖。

参数 类型 默认值 说明
name string "" alarm 名称
alarmInfo.when number 绝对触发时间(epoch ms),与 delay 二选一
alarmInfo.delayInMinutes number 首次触发延迟(分钟)
alarmInfo.periodInMinutes number 重复周期(分钟),最小 0.5
// 上下文:Service Worker
await chrome.alarms.create("sync", {
  delayInMinutes: 1,
  periodInMinutes: 30
});

// 错误:MV3 的 SW 会休眠,setInterval 不可靠
// setInterval(sync, 1800000); // 错误:SW 休眠后定时丢失

get(name?)

获取指定 alarm,返回 Alarm | undefined

// 上下文:Service Worker
const a = await chrome.alarms.get("sync");
console.log(a?.scheduledTime);

getAll()

返回所有 alarm 数组。

// 上下文:Service Worker
const all = await chrome.alarms.getAll();

clear(name?) / clearAll()

清除指定或全部 alarm,返回 Promise<boolean>

// 上下文:Service Worker
await chrome.alarms.clear("sync");
await chrome.alarms.clearAll();

onAlarm

alarm 到期触发,回调收到 Alarm 对象(含 namescheduledTimeperiodInMinutes)。

// 上下文:Service Worker
chrome.alarms.onAlarm.addListener((alarm) => {
  if (alarm.name === "sync") doSync();
});

chrome.commands

manifest 需声明 commands 键。无需 permission。绑定键盘快捷键。

getAll()

返回已注册命令及其当前快捷键。

// 上下文:Service Worker
const cmds = await chrome.commands.getAll();
cmds.forEach((c) => console.log(c.name, c.shortcut));

onCommand

自定义命令触发时回调 (command, tab)。保留命令 _execute_action(打开 popup)与 _execute_browser_action 由浏览器直接处理,不触发 onCommand

// 上下文:Service Worker
chrome.commands.onCommand.addListener((command, tab) => {
  if (command === "toggle-feature") {
    chrome.tabs.sendMessage(tab.id, { type: "toggle" });
  }
});

manifest 配置示例:

{
  "commands": {
    "toggle-feature": {
      "suggested_key": { "default": "Ctrl+Shift+Y" },
      "description": "切换功能"
    },
    "_execute_action": {
      "suggested_key": { "default": "Ctrl+Shift+U" }
    }
  }
}

chrome.notifications

notifications 权限。

create(notificationId?, options)

创建系统通知,返回最终 notificationId

参数 类型 默认值 说明
notificationId string 自动生成 省略则随机生成
options.type string 必填 "basic"/"image"/"list"/"progress"
options.iconUrl string 必填 图标 URL(扩展内资源)
options.title string 必填 标题
options.message string 必填 正文
options.buttons object[] 最多 2 个,{ title }
options.priority number 0 -2 到 2
// 上下文:Service Worker
await chrome.notifications.create("done", {
  type: "basic",
  iconUrl: chrome.runtime.getURL("icon128.png"),
  title: "任务完成",
  message: "已同步 5 项",
  buttons: [{ title: "查看" }]
});

update(notificationId, options)

更新已有通知,返回 Promise<boolean>(是否存在)。

// 上下文:Service Worker
await chrome.notifications.update("done", { message: "已同步 6 项" });

clear(notificationId)

清除通知,返回 Promise<boolean>

// 上下文:Service Worker
await chrome.notifications.clear("done");

onClicked / onButtonClicked

通知本体或按钮被点击时触发。

// 上下文:Service Worker
chrome.notifications.onClicked.addListener((id) => {
  console.log("点击通知", id);
});
chrome.notifications.onButtonClicked.addListener((id, btnIndex) => {
  if (id === "done" && btnIndex === 0) chrome.tabs.create({ url: "result.html" });
});

chrome.sidePanel

sidePanel 权限,Chrome 114+。manifest 可配 side_panel.default_path

setPanelBehavior(behavior)

控制点击工具栏图标是否打开侧边栏。

参数 类型 默认值 说明
behavior.openPanelOnActionClick boolean false 点图标即开侧边栏
// 上下文:Service Worker
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true });

setOptions(options)

为全局或指定标签设置侧边栏页面与启用状态。

参数 类型 默认值 说明
options.tabId number 全局 限定标签
options.path string 侧边栏 HTML 路径
options.enabled boolean true 是否在该标签启用
// 上下文:Service Worker
await chrome.sidePanel.setOptions({
  tabId,
  path: "panel.html",
  enabled: true
});

open(options)

以编程方式打开侧边栏。必须在用户手势回调内调用(如 onClicked、onCommand)。

参数 类型 默认值 说明
options.tabId number 在该标签打开(与 windowId 二选一)
options.windowId number 在该窗口打开
// 上下文:Service Worker(用户手势内)
chrome.action.onClicked.addListener(async (tab) => {
  await chrome.sidePanel.open({ tabId: tab.id });
});

// 错误:在非手势上下文(如 alarm)调用会被拒绝
// chrome.alarms.onAlarm.addListener(() => chrome.sidePanel.open({...})); // 错误:无手势

getOptions(options)

查询当前侧边栏配置。

// 上下文:Service Worker
const opts = await chrome.sidePanel.getOptions({ tabId });

chrome.permissions

无需 permission。运行时申请 manifest optional_permissions / optional_host_permissions 中声明的可选权限。

contains(permissions)

检查是否已拥有某权限,返回 Promise<boolean>

参数 类型 默认值 说明
permissions.permissions string[] [] API 权限名
permissions.origins string[] [] host 权限 match pattern
// 上下文:页面或 Service Worker
const has = await chrome.permissions.contains({ permissions: ["downloads"] });

request(permissions)

弹窗请求权限,返回 Promise<boolean>必须在用户手势内调用

// 上下文:popup(按钮点击回调内)
button.addEventListener("click", async () => {
  const granted = await chrome.permissions.request({
    permissions: ["downloads"],
    origins: ["https://*.example.com/*"]
  });
  if (granted) startDownload();
});

// 错误:页面加载时直接请求,无手势会失败
// window.onload = () => chrome.permissions.request({...}); // 错误:无用户手势

remove(permissions)

撤销已授予的可选权限,返回 Promise<boolean>

// 上下文:页面或 Service Worker
await chrome.permissions.remove({ permissions: ["downloads"] });

getAll()

返回当前所有有效权限(含 manifest 静态权限与已授予的可选权限)。

// 上下文:页面或 Service Worker
const all = await chrome.permissions.getAll();
console.log(all.permissions, all.origins);

chrome.cookies

cookies 权限 + 目标域的 host 权限。

get(details)

读取单个 Cookie,返回 Cookie | null

参数 类型 默认值 说明
details.url string 必填 Cookie 所属 URL
details.name string 必填 Cookie 名
details.storeId string 当前 Cookie store ID
// 上下文:Service Worker(需 host 权限)
const c = await chrome.cookies.get({ url: "https://example.com", name: "sid" });
console.log(c?.value);

getAll(details)

按条件批量获取 Cookie,返回 Cookie[]

参数 类型 默认值 说明
details.domain string 不限 域过滤
details.name string 不限 名称过滤
details.url string 不限 URL 过滤
details.secure boolean 不限 仅安全 Cookie
// 上下文:Service Worker
const cookies = await chrome.cookies.getAll({ domain: "example.com" });

set(details)

写入或更新 Cookie,返回写入的 Cookie

参数 类型 默认值 说明
details.url string 必填 关联 URL
details.name string "" Cookie 名
details.value string "" Cookie 值
details.expirationDate number 会话级 epoch 秒,省略为会话 Cookie
details.httpOnly boolean false 是否 HttpOnly
details.sameSite string "unspecified" "no_restriction"/"lax"/"strict"
// 上下文:Service Worker
await chrome.cookies.set({
  url: "https://example.com",
  name: "theme",
  value: "dark",
  expirationDate: Math.floor(Date.now() / 1000) + 86400
});

remove(details)

删除 Cookie。

// 上下文:Service Worker
await chrome.cookies.remove({ url: "https://example.com", name: "theme" });

onChanged

Cookie 增删改时触发。回调 changeInfocookieremovedcause

// 上下文:Service Worker
chrome.cookies.onChanged.addListener((info) => {
  console.log(info.cause, info.removed, info.cookie.name);
});

chrome.webNavigation

webNavigation 权限。监听页面导航各阶段。所有事件支持 addListener(cb, filter?)filter.url 可按 URL 条件过滤。回调含 tabIdframeIdurltimeStamp

onCommitted

导航已确定并开始加载文档时触发(此时 URL 与导航类型已定)。

// 上下文:Service Worker
chrome.webNavigation.onCommitted.addListener((d) => {
  if (d.frameId === 0) console.log("主框架导航至", d.url, d.transitionType);
}, { url: [{ hostSuffix: "example.com" }] });

onCompleted

文档及子资源加载完成时触发。

// 上下文:Service Worker
chrome.webNavigation.onCompleted.addListener((d) => {
  if (d.frameId === 0) console.log("加载完成", d.url);
});

onHistoryStateUpdated

SPA 通过 history.pushState/replaceState 改变 URL 而无整页刷新时触发,是监听单页应用路由变化的关键。

// 上下文:Service Worker
chrome.webNavigation.onHistoryStateUpdated.addListener((d) => {
  console.log("SPA 路由变化", d.url);
});

其它常用事件:onBeforeNavigate(导航即将发生)、onDOMContentLoaded(DOM 就绪)、onErrorOccurred(导航失败)、onReferenceFragmentUpdated(仅 # 锚点变化)、onCreatedNavigationTarget(新标签/窗口被创建为导航目标)。


chrome.declarativeNetRequest

declarativeNetRequest(可阻塞)或 declarativeNetRequestWithHostAccess(仅在有 host 权限的请求上生效)。声明式拦截/改写网络请求,无需读取请求内容,性能与隐私优于已废弃的阻塞式 webRequest

规则数量上限:静态规则跨启用 ruleset 保底 30,000 条(GUARANTEED_MINIMUM_STATIC_RULES);动态规则上限 30,000MAX_NUMBER_OF_DYNAMIC_RULES);会话规则上限 5,000MAX_NUMBER_OF_SESSION_RULES);静态 ruleset 总数 100,同时启用至多 50。规则 action.type 取值:"block"(拦截)、"redirect"(重定向)、"allow"(放行,优先于 block)、"upgradeScheme"(HTTP 升级 HTTPS)、"modifyHeaders"(改写请求/响应头)。

updateDynamicRules(options)

增删动态规则(跨会话持久),返回 Promise<void>

参数 类型 默认值 说明
options.addRules Rule[] [] 新增规则
options.removeRuleIds number[] [] 按 ID 删除,先删后加
// 上下文:Service Worker
await chrome.declarativeNetRequest.updateDynamicRules({
  removeRuleIds: [1],
  addRules: [{
    id: 1,
    priority: 1,
    action: { type: "block" },
    condition: {
      urlFilter: "||ads.example.com",
      resourceTypes: ["script", "image"]
    }
  }]
});

getDynamicRules(filter?)

返回当前动态规则。

// 上下文:Service Worker
const rules = await chrome.declarativeNetRequest.getDynamicRules();

updateSessionRules(options)

增删会话规则(浏览器关闭即清除,不写磁盘),参数同 updateDynamicRules

// 上下文:Service Worker
await chrome.declarativeNetRequest.updateSessionRules({
  addRules: [{
    id: 100,
    priority: 1,
    action: {
      type: "modifyHeaders",
      requestHeaders: [{ header: "x-tag", operation: "set", value: "ext" }]
    },
    condition: { urlFilter: "||api.example.com", resourceTypes: ["xmlhttprequest"] }
  }]
});

getSessionRules()

返回当前会话规则。

// 上下文:Service Worker
const session = await chrome.declarativeNetRequest.getSessionRules();

静态规则在 manifest 的 declarative_net_request.rule_resources 中以 JSON 文件声明,随扩展打包,适合稳定的大规模过滤列表:

{
  "declarative_net_request": {
    "rule_resources": [{
      "id": "ruleset_1",
      "enabled": true,
      "path": "rules.json"
    }]
  }
}

chrome.identity

identity 权限。OAuth2 与第三方登录。

getAuthToken(details?)

获取 Google OAuth2 令牌(仅限 Google 账户场景),返回 { token, grantedScopes }。需在 manifest 配 oauth2.client_idscopes

参数 类型 默认值 说明
details.interactive boolean false 是否允许弹出登录界面
details.scopes string[] manifest 配置 覆盖默认 scope
// 上下文:Service Worker 或页面
const { token } = await chrome.identity.getAuthToken({ interactive: true });
const res = await fetch("https://www.googleapis.com/oauth2/v1/userinfo", {
  headers: { Authorization: `Bearer ${token}` }
});

launchWebAuthFlow(details)

通用 OAuth2 流程(适配任意第三方 IdP),打开授权页并在重定向回 getRedirectURL() 时返回最终 URL。

参数 类型 默认值 说明
details.url string 必填 授权端点完整 URL
details.interactive boolean false 是否显示授权界面
// 上下文:页面(用户手势内)
const redirectUrl = chrome.identity.getRedirectURL();
const authUrl = `https://github.com/login/oauth/authorize?client_id=ID&redirect_uri=${encodeURIComponent(redirectUrl)}`;
const resultUrl = await chrome.identity.launchWebAuthFlow({
  url: authUrl,
  interactive: true
});
const code = new URL(resultUrl).searchParams.get("code");

getRedirectURL(path?)

同步返回 https://<extension-id>.chromiumapp.org/<path> 形式的回调 URL,用于在 IdP 注册 redirect_uri。

// 上下文:任意
console.log(chrome.identity.getRedirectURL("cb"));
// https://abcdefg.chromiumapp.org/cb

chrome.offscreen

offscreen 权限。MV3 的 SW 无 DOM、无 window,本 API 创建隐藏文档以执行需要 DOM 的操作(解析 HTML、读剪贴板、播放音频等)。同一时刻只能有一个 offscreen 文档(split 模式下普通与隐身各一个)。

createDocument(parameters)

创建 offscreen 文档,加载完成后 resolve。

参数 类型 默认值 说明
parameters.url string 必填 扩展内 HTML 相对路径
parameters.reasons string[] 必填 用途枚举,见下
parameters.justification string 必填 给审核与用户看的理由说明

reasons 取值:"AUDIO_PLAYBACK"(播放音频)、"CLIPBOARD"(读写剪贴板)、"DOM_PARSER"(用 DOMParser)、"DOM_SCRAPING"(解析抓取 DOM)、"BLOBS"(创建对象 URL)、"IFRAME_SCRIPTING""USER_MEDIA""DISPLAY_MEDIA""WEB_RTC""LOCAL_STORAGE""WORKERS""BATTERY_STATUS""MATCH_MEDIA""GEOLOCATION""TESTING"

// 上下文:Service Worker
async function ensureOffscreen() {
  const existing = await chrome.runtime.getContexts({
    contextTypes: ["OFFSCREEN_DOCUMENT"]
  });
  if (existing.length) return; // 已存在则跳过,避免重复创建报错
  await chrome.offscreen.createDocument({
    url: "offscreen.html",
    reasons: ["DOM_PARSER"],
    justification: "解析远程返回的 HTML 片段"
  });
}

// 错误:未判重,第二次创建直接抛 "Only a single offscreen document may be created"
// await chrome.offscreen.createDocument({...}); // 错误:重复创建

closeDocument()

关闭当前 offscreen 文档,无参数,返回 Promise<void>

// 上下文:Service Worker
await chrome.offscreen.closeDocument();

hasDocument()

返回是否存在 offscreen 文档。注意:此为旧式判断,新代码推荐 chrome.runtime.getContexts

// 上下文:Service Worker
if (!(await chrome.offscreen.hasDocument())) {
  await chrome.offscreen.createDocument({ /* ... */ });
}

chrome.i18n

无需 permission,但需建立 _locales/<lang>/messages.json 并在 manifest 设 default_locale

getMessage(messageName, substitutions?)

同步返回当前 UI 语言对应的本地化字符串。

参数 类型 默认值 说明
messageName string 必填 messages.json 中的键名
substitutions string | string[] 替换 $1-$9 占位符,最多 9 个
// 上下文:任意
const title = chrome.i18n.getMessage("appTitle");
const greet = chrome.i18n.getMessage("greet", ["小明"]); // "你好,小明"

_locales/zh_CN/messages.json

{
  "appTitle": { "message": "我的扩展" },
  "greet": { "message": "你好,$1", "placeholders": {} }
}

getUILanguage()

同步返回浏览器 UI 语言(如 "zh-CN"),无参数。

// 上下文:任意
console.log(chrome.i18n.getUILanguage());

detectLanguage(text)

检测文本语言,返回 { isReliable, languages: [{ language, percentage }] }

参数 类型 默认值 说明
text string 必填 待检测文本
// 上下文:任意
const r = await chrome.i18n.detectLanguage("这是一段中文");
console.log(r.languages[0].language); // "zh"

chrome.downloads

downloads 权限。

download(options)

发起下载,返回 downloadId

参数 类型 默认值 说明
options.url string 必填 下载地址
options.filename string 服务器推断 相对默认下载目录的路径
options.saveAs boolean false 是否弹「另存为」
options.conflictAction string "uniquify" "uniquify"/"overwrite"/"prompt"
// 上下文:Service Worker 或页面
const id = await chrome.downloads.download({
  url: "https://example.com/report.pdf",
  filename: "reports/report.pdf"
});

其它常用:search(query) 查询下载项、cancel(id) 取消、pause(id) / resume(id) 暂停恢复、onChanged 监听状态变化。


chrome.bookmarks

bookmarks 权限。

create(bookmark)

创建书签或文件夹(省略 url 即文件夹),返回 BookmarkTreeNode

参数 类型 默认值 说明
bookmark.parentId string 「其他书签」 父节点 ID
bookmark.title string "" 标题
bookmark.url string 无(=文件夹) 链接地址
bookmark.index number 末尾 在父节点中的位置
// 上下文:Service Worker 或页面
const node = await chrome.bookmarks.create({
  title: "Chrome 扩展文档",
  url: "https://developer.chrome.com/docs/extensions"
});

其它常用:search(query) 搜索、getTree() 取完整树、remove(id) / removeTree(id) 删除、update(id, changes) 改标题或 URL、move(id, dest) 移动。


chrome.history

history 权限。

search(query)

搜索浏览历史,返回 HistoryItem[]

参数 类型 默认值 说明
query.text string ""(全部) 模糊匹配 URL/标题
query.startTime number 24 小时前 起始时间 epoch ms
query.endTime number 现在 结束时间
query.maxResults number 100 返回上限
// 上下文:Service Worker 或页面
const items = await chrome.history.search({
  text: "github",
  maxResults: 20
});

其它常用:addUrl({ url }) 添加访问记录、deleteUrl({ url }) 删除某 URL、deleteRange({ startTime, endTime }) 按时间段删、getVisits({ url }) 取访问明细、onVisited / onVisitRemoved 事件。


最佳实践

1. 批量读写 storage,避免逐条操作

set/get 接受多键对象,一次调用比循环多次调用快得多,且能规避 sync 区每分钟 120 次的写频率上限。

// 推荐:单次写多键
await chrome.storage.local.set({ a: 1, b: 2, c: 3 });

// 错误:循环逐条,慢且易触限流
// for (const [k, v] of entries) await chrome.storage.sync.set({ [k]: v }); // 错误:高频写

2. tabs.query 必须带条件,杜绝全表扫描

无条件 query({}) 返回所有窗口所有标签,浪费且需更宽权限。绝大多数场景只需当前激活标签。

// 推荐:精确锁定
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });

3. 用 alarms 替代 setTimeout/setInterval

MV3 的 SW 空闲约 30 秒后被回收,定时器随之失效。持久定时任务一律用 chrome.alarms,并记得最小周期 0.5 分钟。

// 推荐
chrome.runtime.onInstalled.addListener(() => {
  chrome.alarms.create("poll", { periodInMinutes: 5 });
});
chrome.alarms.onAlarm.addListener((a) => a.name === "poll" && poll());

4. 异步消息回复显式 return true,或返回 Promise

onMessage 监听器若在异步操作后调用 sendResponse,未 return true 会导致通道提前关闭、响应丢失。Chrome 148+ 可直接返回 Promise 替代。

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  fetchData().then(sendResponse);
  return true; // 推荐:保持通道
});

5. offscreen / 资源创建前先判重

offscreen 文档全局仅一个,重复 createDocument 直接抛错。创建前用 getContexts 检查,contextMenus 则在 onInstalled 中创建以避免 SW 多次唤醒重复添加。

const has = (await chrome.runtime.getContexts({
  contextTypes: ["OFFSCREEN_DOCUMENT"]
})).length > 0;
if (!has) await chrome.offscreen.createDocument({ /* ... */ });

6. 优先 declarativeNetRequest 而非阻塞式 webRequest

MV3 已移除阻塞式 webRequest。请求拦截/改写改用声明式规则,性能更高且无需读取请求体。频繁变动的规则用 updateDynamicRules,临时规则用会话规则。

await chrome.declarativeNetRequest.updateDynamicRules({
  addRules: [{ id: 1, priority: 1, action: { type: "block" },
    condition: { urlFilter: "||tracker.com", resourceTypes: ["script"] } }]
});

7. 运行时权限按需申请,缩小默认权限面

把非核心权限放进 optional_permissions,在用户触发对应功能时用 permissions.request(须在手势内)申请,既过审更顺利,也减少安装时的权限警告。

btn.onclick = async () => {
  if (await chrome.permissions.request({ permissions: ["cookies"] })) {
    readCookies();
  }
};

常见陷阱

陷阱 1:executeScript 的 func 无法访问外部闭包变量

  • 现象:func: () => useExternal 在目标页执行时报 useExternal is not defined
  • 原因:func 会被序列化为字符串发送到目标页进程执行,与 SW 作用域完全隔离,闭包不跨进程。
  • 解决:所有外部数据通过 args 数组传入,且必须 JSON 可序列化。
const value = 42;
await chrome.scripting.executeScript({
  target: { tabId },
  func: (v) => { document.title = v; }, // 通过参数接收
  args: [value]
});

陷阱 2:tabs.sendMessage 目标无内容脚本时抛错

  • 现象:调用 chrome.tabs.sendMessageCould not establish connection. Receiving end does not exist.
  • 原因:目标标签尚未注入内容脚本(如 chrome:// 页、刚打开未匹配的页、CS 注入失败)。
  • 解决:用 try/catch 包裹;或先 executeScript 确保 CS 存在,再发消息。
try {
  await chrome.tabs.sendMessage(tabId, { ping: 1 });
} catch {
  await chrome.scripting.executeScript({ target: { tabId }, files: ["cs.js"] });
  await chrome.tabs.sendMessage(tabId, { ping: 1 });
}

陷阱 3:storage.sync 静默超配额导致写入失败

  • 现象:写入大对象后读回为空或报错,但小数据正常。
  • 原因:sync 单项上限 8 KB、总量 100 KB、最多 512 项,超限的 set 会通过 runtime.lastError 报错而非抛异常,容易被忽略。
  • 解决:大数据放 local(10 MB);sync 只存小配置;写前用 getBytesInUse 估算,Promise 风格用 try/catch 捕获超配额错误。
try {
  await chrome.storage.sync.set({ bigBlob: hugeString }); // 可能超 8KB/项
} catch (e) {
  console.warn("sync 超配额,降级到 local:", e.message);
  await chrome.storage.local.set({ bigBlob: hugeString });
}

陷阱 4:sidePanel.open / permissions.request 在非手势上下文被拒

  • 现象:在 alarmonMessage、页面加载等非用户手势回调中调用,方法静默失败或报错。
  • 原因:这两个 API 出于安全要求必须由用户手势(点击、快捷键)直接触发。
  • 解决:只在 action.onClickedcommands.onCommand、DOM click 等手势回调内调用,且避免在手势回调里先 await 其它异步操作再调用(部分浏览器会判定手势已失效)。

参见

阅读更多

Web 安全基础

1. HTML 转义(服务端渲染必须): 2. CSP(Content Security Policy): 3. HttpOnly Cookie:防止 JS 读取会话 Cookie: 4. 前端框架防护: 攻击者在第三方网站构造一个表单,诱导已登录用户提交,浏览器会自动携带目标站的 Cookie。 触发条件: 1. 用户已登录目标网站(Cookie 有效) 2. 目标 API 仅凭 Cookie 识别用户身份 3. 请求来源未验证 1. CSRF Token(推荐): 2. SameSite Cookie: 3. 验证 Origin/Referer 头:

By yellowdog

HTTP 协议深度指南

HTTP(HyperText Transfer Protocol)是 Web 的基础传输协议,基于 TCP/IP,采用请求/响应模型。 相关文档:Web安全基础(/web-an-quan-ji-chu/) FastAPI完全指南(/fastapi-wan-quan-zhi-nan/) Nginx完全指南(/nginx-wan-quan-zhi-nan/) 幂等性:多次执行相同请求,服务器状态结果相同。PUT /users/1 多次执行结果一致;POST /users 每次创建新资源,非幂等。 浏览器直接从本地缓存读取,不向服务器发送请求。 缓存命中时,状

By yellowdog

系统设计基础

SLA 对照表: 选择建议:无状态服务(Web 层、API 层)优先水平扩展;数据库初期垂直扩展,达到瓶颈后考虑分库分表或读写分离。 缓存穿透(查询不存在的 key,每次都打到 DB): 缓存击穿(热点 key 过期,瞬间大量请求打到 DB): 缓存雪崩(大量 key 同时过期,或缓存服务宕机): 令牌桶 Python 实现: Redis 实现分布式限流(滑动窗口): URL 命名规则: Cursor 分页响应格式: 雪花算法结构(64 bit): 定义:分布式系统不能同时满足以下三个特性: 在分布式环境中 P 是必须保证的,所以实际是 CP vs AP

By yellowdog

算法思路与模板

二分查找要求序列有序,每次将搜索范围缩减一半,时间复杂度 O(log n)。 两个指针从两端向中间收缩,常用于有序数组。 滑动窗口维护一个满足条件的区间 left, right,right 不断向右扩张,条件不满足时收缩 left。 滑动窗口通用框架: 1. 确定"子问题":原问题可以分解为哪些规模更小的同类问题 2. 定义 dpi 或 dpij 的含义,要足够清晰 3. 推导状态转移方程 4. 确定初始状态(边界条件) 5. 确定计算顺序(确保依赖的子问题先计算) 每件物品最多选一次。dpj = 容量为 j 时的最大价值,逆序遍历容量防止重复选取。 每

By yellowdog