webRequest.onAuthRequired

当服务器发送 401407 状态码并使用 Basic 方案的 WWW-Authenticate 头时(即服务器要求客户端提供身份验证凭据,例如用户名和密码时),此事件被触发。

监听器可以以以下四种方式之一响应:

不采取任何行动

监听器可以不做任何事情,只是观察请求。如果发生这种情况,它不会影响请求的处理,并且浏览器会酌情要求用户登录。

取消请求

监听器可以取消请求。如果这样做,身份验证将失败,并且不会要求用户登录。扩展可以通过以下方式取消请求:

  • 在 addListener 中,在 extraInfoSpec 参数中传入 "blocking"
  • 在监听器中,返回一个带有 cancel 属性并设置为 true 的对象
同步提供凭据

如果凭据可以同步获取,扩展可以同步提供它们。如果扩展这样做,浏览器会尝试使用这些凭据登录。监听器可以通过以下方式同步提供凭据:

  • 在 addListener 中,在 extraInfoSpec 参数中传入 "blocking"
  • 在监听器中,返回一个带有 authCredentials 属性并设置为要提供的凭据的对象
异步提供凭据

扩展可能需要异步获取凭据。例如,扩展可能需要从存储中获取凭据或询问用户。在这种情况下,监听器可以通过以下方式异步提供凭据:

  • 在 addListener 中,在 extraInfoSpec 参数中传入 Chrome 和 Firefox 中的 "asyncBlocking" 或 Firefox 中的 "blocking"

  • 如果提供了 "blocking",扩展可以返回一个 webRequest.BlockingResponse 对象或一个解析为 webRequest.BlockingResponse 对象的 Promise

  • 如果提供了 "asyncBlocking",事件监听函数将接收一个 asyncCallback 函数作为其第二个参数。asyncCallback 可以异步调用,并接受一个 webRequest.BlockingResponse 对象作为其唯一参数

    注意:Chrome 不支持 Promise 作为返回值(Chromium 问题 1510405)。有关替代方案,请参阅 listener 的返回值

请参阅示例

如果您的扩展提供错误的凭据,那么监听器将再次被调用。因此,请注意避免通过重复提供错误的凭据而进入无限循环。

Permissions

在 Firefox 和 Chrome Manifest V2 扩展中,您必须将"webRequest""webRequestBlocking" API 权限添加到您的 manifest.json 中。

对于 Manifest V3 扩展,Chrome 不再支持 "webRequestBlocking" 权限(策略安装的扩展除外)。相反,"webRequest""webRequestAuthProvider" 权限允许您异步提供凭据。Firefox 继续支持 Manifest V3 中的 "webRequestBlocking" 并提供 "webRequestAuthProvider" 以提供跨浏览器兼容性。

代理授权

Firefox 通常不会为系统请求(例如浏览器或扩展升级或搜索引擎查询)触发 webRequest 事件。为了使代理授权能够顺利地用于系统请求,从版本 57 开始,Firefox 支持一个例外。

如果扩展具有 "webRequest""webRequestBlocking""proxy""<all_urls>" 权限,那么它可以使用 onAuthRequired 为代理授权提供凭据(但不能用于正常的网络授权)。监听器不能取消系统请求或对任何系统请求进行任何其他修改。

语法

js
browser.webRequest.onAuthRequired.addListener(
  listener,                    // function
  filter,                      //  object
  extraInfoSpec                //  optional array of strings
)
browser.webRequest.onAuthRequired.removeListener(listener)
browser.webRequest.onAuthRequired.hasListener(listener)

事件有三个函数

addListener(listener, filter, extraInfoSpec)

向此事件添加监听器。

removeListener(listener)

停止监听此事件。listener 参数是要移除的监听器。

hasListener(listener)

检查 listener 是否已为此事件注册。如果正在监听,则返回 true,否则返回 false

addListener 语法

参数

监听器

此事件发生时调用的函数。该函数会传递以下参数:

details

object。有关请求的详细信息。有关更多信息,请参阅 details 部分。

asyncCallback 可选

一个最多调用一次的函数,用于异步修改请求对象。此参数仅在事件监听器使用 extraInfoSpec 数组中的 "asyncBlocking" 注册时才存在。如果未提供 extraInfoSpec 或包含 "blocking",则 asyncCallback 未定义。

返回:webRequest.BlockingResponsePromise,具体取决于 extraInfoSpec 中的设置。

filter

webRequest.RequestFilter。一个限制发送到此监听器的事件的过滤器。

extraInfoSpec 可选

array 类型的 string。事件的额外选项。您可以传递以下任何值:

  • "blocking":使请求阻塞,以便您可以取消请求或提供身份验证凭据。返回一个 BlockingResponse 对象,并设置其 cancelauthCredentials 属性。

    • 在 Chrome 中,事件监听器必须同步响应。
    • 在 Firefox 中,事件监听器可以同步响应或返回一个解析为 BlockingResponse 对象的 Promise 以异步响应。
  • "asyncBlocking":异步处理请求。事件监听器的返回值将被忽略。要解决事件,请将 asyncCallback 参数传递一个 BlockingResponse 对象。

    • Chrome 120 和 Firefox 128 开始支持。
    • Safari 不支持。

额外对象

details

challenger

object。请求身份验证的服务器。这是一个包含以下属性的对象:

主机

string。服务器的主机名

port

integer。服务器的端口号。

cookieStoreId

string。如果请求来自上下文身份中打开的标签页,则为上下文身份的 cookie 存储 ID。有关更多信息,请参阅使用上下文身份

frameId

integer。如果请求发生在主框架中,则为 0;正值表示请求发生的子框架的 ID。如果加载了(子)框架的文档(typemain_framesub_frame),frameId 表示此框架的 ID,而不是外部框架的 ID。框架 ID 在一个标签页内是唯一的。

incognito

boolean。请求是否来自隐私浏览窗口。

isProxy

boolean。对于 Proxy-Authenticatetrue,对于 WWW-Authenticatefalse

注意:webRequest.onAuthRequired 仅在需要身份验证的 HTTP 和 HTTPS/TLS 代理服务器上调用,而不在需要身份验证的 SOCKS 代理服务器上调用。

method(方法)

string。标准 HTTP 方法(例如,"GET""POST")。

parentFrameId

integer。包含发送请求的框架的框架的 ID。如果没有父框架,则设置为 -1

proxyInfo

object。此属性仅在请求通过代理时存在。它包含以下属性:

主机

string。代理服务器的主机名。

port

integer。代理服务器的端口号。

type

string。代理服务器的类型。以下之一:

  • "http":HTTP 代理(或 HTTPS 的 SSL CONNECT)
  • "https":通过 TLS 连接到代理的 HTTP 代理
  • "socks":SOCKS v5 代理
  • "socks4":SOCKS v4 代理
  • "direct":无代理
  • "unknown":未知代理
username

string。代理服务的用户名。

proxyDNS

boolean。如果代理根据提供的主机名执行域名解析,则为 True,这意味着客户端不应自行进行 DNS 查找。

failoverTimeout

integer。故障转移超时(秒)。如果连接在此秒数后未能连接到代理服务器,则使用从FindProxyForURL()返回的数组中的下一个代理服务器。

realm 可选

string。如果存在,服务器提供的身份验证领域

requestId

string。请求的 ID。请求 ID 在浏览器会话中是唯一的,因此您可以关联与同一请求相关的不同事件。

responseHeaders 可选

webRequest.HttpHeaders。此响应收到的 HTTP 响应头。

scheme

string。身份验证方案:"basic""digest"

statusCode

integer。服务器返回的标准 HTTP 状态码。

statusLine

string。响应的 HTTP 状态行,HTTP/0.9 响应的 'HTTP/0.9 200 OK' 字符串(即缺少状态行的响应),如果没有任何头,则为空字符串。

tabId

integer。请求发生的标签页的 ID。如果请求与标签页无关,则设置为 -1

thirdParty

boolean。指示请求及其内容窗口层次结构是否是第三方。

timeStamp

number。此事件触发的时间,以纪元以来的毫秒数表示。

type

webRequest.ResourceType。正在请求的资源的类型:例如,"image""script""stylesheet"

url

string。请求的目标。

urlClassification

object。如果请求被Firefox 跟踪保护分类,则与请求关联的跟踪类型。这是一个包含以下属性的对象:

firstParty

array 类型的 string。请求的第一方分类标志。

thirdParty

array 类型的 string。请求或其窗口层次结构的第三方分类标志。

分类标志包括:

  • fingerprintingfingerprinting_content:表示请求涉及指纹识别(“发现指纹识别的来源”)。
    • fingerprinting 表示该域属于指纹识别和跟踪类别。此类域的示例包括希望将配置文件与访问用户关联的广告商。
    • fingerprinting_content 表示该域属于指纹识别类别但不属于跟踪类别。此类域的示例包括使用指纹识别技术识别访问用户以进行反欺诈目的的支付提供商。
  • cryptominingcryptomining_content:类似于指纹识别类别,但用于加密挖矿资源。
  • trackingtracking_adtracking_analyticstracking_socialtracking_content:表示请求涉及跟踪。tracking 是任何通用跟踪请求。adanalyticssocialcontent 后缀标识跟踪器的类型。
  • emailtrackingemailtracking_content:表示请求涉及跟踪电子邮件。
  • any_basic_tracking:一个元标志,结合了跟踪和指纹识别标志,不包括 tracking_contentfingerprinting_content
  • any_strict_tracking:一个元标志,结合了所有跟踪和指纹识别标志。
  • any_social_tracking:一个元标志,结合了所有社交跟踪标志。

您可以在 disconnect.me 网站上找到有关跟踪器类型的更多信息。content 后缀表示跟踪并提供内容的跟踪器。阻止它们可以保护用户,但也可能导致网站损坏或元素无法显示。

示例

此代码观察目标 URL 的身份验证请求

js
const target = "https://intranet.company.com/";

function observe(requestDetails) {
  console.log(`observing: ${requestDetails.requestId}`);
}

browser.webRequest.onAuthRequired.addListener(observe, { urls: [target] });

此代码取消目标 URL 的身份验证请求

js
const target = "https://intranet.company.com/";

function cancel(requestDetails) {
  console.log(`canceling: ${requestDetails.requestId}`);
  return { cancel: true };
}

browser.webRequest.onAuthRequired.addListener(cancel, { urls: [target] }, [
  "blocking",
]);

此代码同步提供凭据。它跟踪未完成的请求,以确保不会重复提交错误的凭据

js
const target = "https://intranet.company.com/";

const myCredentials = {
  username: "me@company.com",
  password: "zDR$ERHGDFy",
};

const pendingRequests = [];

// A request has completed.
// We can stop worrying about it.
function completed(requestDetails) {
  console.log(`completed: ${requestDetails.requestId}`);
  let index = pendingRequests.indexOf(requestDetails.requestId);
  if (index > -1) {
    pendingRequests.splice(index, 1);
  }
}

function provideCredentialsSync(requestDetails) {
  // If we have seen this request before, then
  // assume our credentials were bad, and give up.
  if (pendingRequests.includes(requestDetails.requestId)) {
    console.log(`bad credentials for: ${requestDetails.requestId}`);
    return { cancel: true };
  }
  pendingRequests.push(requestDetails.requestId);
  console.log(`providing credentials for: ${requestDetails.requestId}`);
  return { authCredentials: myCredentials };
}

browser.webRequest.onAuthRequired.addListener(
  provideCredentialsSync,
  { urls: [target] },
  ["blocking"],
);

browser.webRequest.onCompleted.addListener(completed, { urls: [target] });

browser.webRequest.onErrorOccurred.addListener(completed, { urls: [target] });

此代码异步提供凭据,从存储中获取它们。它还跟踪未完成的请求,以确保不会重复提交错误的凭据

js
const target = "https://httpbin.org/basic-auth/*";

const pendingRequests = [];

/*
 * A request has completed. We can stop worrying about it.
 */
function completed(requestDetails) {
  console.log(`completed: ${requestDetails.requestId}`);
  let index = pendingRequests.indexOf(requestDetails.requestId);
  if (index > -1) {
    pendingRequests.splice(index, 1);
  }
}

function provideCredentialsAsync(requestDetails) {
  // If we have seen this request before,
  // then assume our credentials were bad,
  // and give up.
  if (pendingRequests.includes(requestDetails.requestId)) {
    console.log(`bad credentials for: ${requestDetails.requestId}`);
    return { cancel: true };
  }
  pendingRequests.push(requestDetails.requestId);
  console.log(`providing credentials for: ${requestDetails.requestId}`);
  // we can return a promise that will be resolved
  // with the stored credentials
  return browser.storage.local.get(null);
}

browser.webRequest.onAuthRequired.addListener(
  provideCredentialsAsync,
  { urls: [target] },
  ["blocking"],
);

browser.webRequest.onCompleted.addListener(completed, { urls: [target] });

browser.webRequest.onErrorOccurred.addListener(completed, { urls: [target] });

扩展程序示例

浏览器兼容性

注意:此 API 基于 Chromium 的 chrome.webRequest API。此文档来源于 Chromium 代码中的 web_request.json