谷歌浏览器插件 chrome.webRequest 技术深度解析

2023-05-16

背景介绍

使用 chrome.webRequest API 观察和分析流量并拦截、阻止或修改正在进行的请求

HTTP请求的生命周期

事件解释
onBeforeRequest当请求即将发生时触发。此事件在建立任何 TCP 连接之前发送,可用于取消或重定向请求。
onBeforeSendHeaders当请求即将发生并且初始标头已准备好时触发。 该事件旨在允许扩展添加、修改和删除请求标头 (*)。 onBeforeSendHeaders 事件传递给所有订阅者,因此不同的订阅者可能会尝试修改请求; 有关如何处理的信息,请参见实施细节部分。 此事件可用于取消请求。
onSendHeaders在所有扩展都有机会修改请求标头后触发,并呈现最终 (*) 版本。 该事件在标头发送到网络之前触发。 此事件是信息性的并且是异步处理的。 它不允许修改或取消请求。
onHeadersReceived每次收到 HTTP(S) 响应标头时触发。 由于重定向和身份验证请求,每个请求可能会发生多次。 此事件旨在允许扩展添加、修改和删除响应标头,例如传入的 Content-Type 标头。 在触发此事件之前会处理缓存指令,因此修改 Cache-Control 等标头对浏览器的缓存没有影响。 它还允许您取消或重定向请求。
onAuthRequired当请求需要对用户进行身份验证时触发。 可以同步处理此事件以提供身份验证凭据。 请注意,扩展可能会提供无效的凭据。 注意不要通过重复提供无效凭据进入无限循环。 这也可以用来取消请求。
onBeforeRedirect在即将执行重定向时触发。重定向可以由 HTTP 响应代码或扩展触发。此事件是信息性的并且是异步处理的。它不允许您修改或取消请求。
onResponseStarted当收到响应body的第一个字节时触发。 对于 HTTP 请求,这意味着状态行和响应标头可用。 此事件是信息性的并且是异步处理的。 它不允许修改或取消请求。
onCompleted成功处理请求时触发。
onErrorOccurred当请求无法成功处理时触发。

认证凭证

webRequest.onAuthRequired

参考文档:

webRequest.onAuthRequired - Mozilla | MDN

这个事件如何触发的?是第一次请求中了 response header 中带有了WWW-Authenticate 与 Proxy-Authenticate 两个 header 标签,此时被识别为需要服务端认证 和 代理认证

补充知识点

认证和授权,英文分别为:authentication 和 permission 这两个词非常重要,认证的意思是你需要带什么凭证我才相信你能进来,授权是我看着你的证件,应该给予你什么权利,举个很好理解的例子:

当你去一个企事业单位,你带着工牌,工牌上的信息,就是认证信息,你拿着这个认证信息是可以进门的,但进门后,需要认证人员来赋予你出入那些地方的凭证,这个新的凭证就是权限,带着这些权限,你才能范围机构内的那些部门,所有的权限都是这样设计的,而一个个授权再一个个比对的话,比较浪费时间。最后就造了角色,比如你是局长,带着局长的牌子就可以出入局长的权利范围内的各个区域

都有那些认证方式?

Basic (查看 RFC 7617, base64编码凭证. 详情请参阅下文.),

Bearer (查看 RFC 6750, bearer 令牌通过OAuth 2.0保护资源)

Digest (查看 RFC 7616, 只有 md5 散列 在Firefox中支持, 查看 bug 472823 用于SHA加密支持),

HOBA (查看 RFC 7486 (草案), HTTP Origin-Bound 认证, 基于数字签名),

Mutual (查看 draft-ietf-httpauth-mutual),

AWS4-HMAC-SHA256 (查看 AWS docs).

Basic 的认证是什么样子的?

  1. 当你刚要进机构的时候,此时会有人说:“请出示你的证件”,他的表现形式就是在 Response 的 header 中给出 WWW-Authenticate: Basic realm="工作人员",realm 是字符串,英文翻译领域,意思就是告诉你,我要的是工作人员的认证信息,如果你上来就进局长门,那么 realm 应该就是局长。

  2. 于是你从口袋里拿出证件,再次交给守卫们,并告诉他,Authorization: Base base64(username:password) ,守卫拿到后,反 base64 后得到你的账号密码,验证你的身份,然后告诉你可以进去了,记得这已经是第二次了

  3. 常规的 http 协议传输,给你感觉是一次调用后就结束了的链接,实际上 http 请求是一个 tcp/ip 长连接下的一种协议传输,平时给你单次连接后断开是是内部程序事件循环调度的结果,浏览器线程一直都开着,tcp/ip 可能一直连接着,所以第一次不成功后返回,但是浏览器并没有直接 response 返回给你,而是问你要凭证,你输入凭证后,程序将带有认证信息头的 http 协议的请求又发了一次,这次就成功了。

详细参考

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Authentication#www-authenticate_%E4%B8%8E_proxy-authenticate_%E9%A6%96%E9%83%A8https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Authentication#www-authenticate_%E4%B8%8E_proxy-authenticate_%E9%A6%96%E9%83%A8

Basic 碰到代理时

Response header: Proxy-Authenticate: <type> realm=<realm>
Request header: Proxy-Authorization: <type> <credentials>

webRequest 的 blocking

blocking 的意思是指,上述的 http 传输过程中,一般程序是不停下来的,比如通知事件是不需要与主线程交互的,主线程就是通知一下子线程,至于你怎么干它不关心。

但是,像要权限这种东西,主线程自己搞不定,他需要你回传认证信息给它,它再重新打包 header 再次发送请求出去,此时你需要让他等一会,这个等待就是关键词 blocking

所以,认证这个环节需要阻塞权限 webRequestBlocking,这个权限类似于开关,你加上这个权限意味着,程序在运行到权限校验时,会判断是否需要等待你返回认证信息,如果你不开启,它就继续走下去,不等待你的返回信息。这个标识在 extraInfoSpec 中填写。

browser.webRequest.onAuthRequired.addListener(

listener, // function

filter, // object

extraInfoSpec // optional array of strings

)

browser.webRequest.onAuthRequired.removeListener(listener)

browser.webRequest.onAuthRequired.hasListener(listener)

其他事件,请自行阅读谷歌文档,说实话,当自己理解了这个概念时,再看谷歌文档,是发现真的比国内的技术文档好太多,一看就是搞技术的人写的,这份认真态度值得学习。

额外注意事项

  1. webrequest 拿到不到 responseBody 怎么办,是的,你没看错,onCompleted 事件中并没有这个东西,此外你如果想要拿到 requestBody 时,在onBeforeRequest 事件中,extraInfoSpec 要增加["requestBody"]返回,此时你知道 extraInfoSpec 的用途了吗,就是一个可变的开关参数,根本不同的事件可能需要返回不同的值或者开关,这个就很好用。

  2. 用 chrome.devtools.network.onRequestFinished 来获取 responseBody 细节请自行谷歌,讲这个有啥用?你的模拟抓取时有用

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.indexOf(requestDetails.requestId) != -1) {
    console.log(`bad credentials for: ${requestDetails.requestId}`);
    return {cancel: true};

  } else {
    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]}
);

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

谷歌浏览器插件 chrome.webRequest 技术深度解析 的相关文章

  • Selenium控制已打开的chrome、IE浏览器

    0 为什么要接管打开的浏览器 1 重复重新登录 过程麻烦 2 拖慢爬虫的运行速度 3 容易让网站检测到账号异常 如何解决重复登录的问题 1 使用登录过的cookie 下次运行时设置保存 2 接管打开的浏览器 也是我们接下来重点讲的 1 控制
  • gzip压缩的json文件在谷歌浏览器(chrome)中可以正常解析,但是在safari浏览器乱码

    gzip压缩的json文件在谷歌浏览器 chrome 中可以正常解析 但是在safari浏览器乱码 挺奇怪的一个问题 json数据通过gzip压缩之后 axios接收到的数据在chrome中是正常的 但是在safari中却是乱码 文件流 后
  • selenium之 chromedriver与chrome版本映射表(更新至v2.46)

    更多关于python selenium的文章 请关注我的专栏 Python Selenium自动化测试详解 看到网上基本没有最新的chromedriver与chrome的对应关系表 便兴起整理了一份如下 希望对大家有用 chromedriv
  • selenium的使用

    selenium的使用 0 使用selenium import time from selenium webdriver import Chrome from selenium webdriver common by import By 1
  • elasticsearch-head chrome 插件安装

    前言 由于不能直接访问谷歌商店下载插件 但可以直接在 Github 下载 地址 https github com mobz elasticsearch head raw master crx es head crx 如果觉得慢 可在此下载
  • python 爬取google总结

    1 问题 目前主流的搜索引擎 非google莫属 但其对于非法 流量异常 爬虫 请求的封锁也是异常严厉 本人前段时间有个脚本用到了谷歌搜索 具体见python之由公司名推算出公司官网 余弦相似度 当时直接使用的是一个python开源项目 但
  • 设置windos电脑开机自动启动chrome浏览器,并且打开指定网页

    需求 web项目设置windos电脑开机自动启动chrome浏览器 打开指定网页地址 并设置为全屏显示 解决 使用windos的bat脚本 设置为开机自启动 代码如下 echo off cd d dp0 title Chrome taskl
  • 无法从传输连接读取数据:C# 中的远程主机强制关闭现有连接

    我有一个代码 我在其中发送 URL 请求并接收响应并将其存储为字符串 public String GenerateXML String q Here q is the URL Generating the XML file for refe
  • 收到响应后使用 Chrome webRequest 进行 URL 转发

    我正在尝试创建一个利用 Chrome 的 Chrome 扩展网络请求模块执行重定向到从最初访问的 URL 获得的 URL 为此 我只想使用 Chrome 的 webRequest 函数 例如 onBeforeSendHeaders onHe
  • 使用 C# 进行远程 HTTP Post [重复]

    这个问题在这里已经有答案了 如何在 C 中执行远程 HTTP Post 请求 这是我曾经编写的一个小应用程序的代码 用于将包含值的表单发布到 URL 它应该非常坚固 formValues 是一个 Dictionary 包含要发布的变量及其值
  • C# WebClient - DownloadString 编码错误

    我正在尝试从 Amazon 下载 html 文档 但由于某种原因 我得到了一个错误的编码字符串 例如 K g g e 这是我尝试过的代码 using var webClient new System Net WebClient var ur
  • 使用 chrome.experimental.webRequest API 更改加载的文件?

    我正在尝试使用 webRequest API 更改网页上加载的 swf 文件 该页面加载一个名为 chat swf 的文件 但我想重定向到同一目录中的 chat2 swf 以便使用另一个文件 有人告诉我这可行 但我不知道如何正确使用这个 A
  • MonoTouch 自动代理网络凭据不起作用

    尝试从我的服务器加载一些数据 xml 数据 我通常只使用 HttpWebRequest 因为我可以将 automaticDecompression 设置为 DecompressionMethods GZip DecompressionMet
  • 使用 c# webrequest 与 asp.net mvc 3 网站交互

    我通过这些操作创建了一个带有家庭控制器的简单 mvc3 站点 public JsonResult Param string id string upper String Concat id ff return Json upper publ
  • 在 Chrome 扩展程序中读取和修改 HTTP GET 请求

    我想在 Chrome 扩展程序中读取和修改 添加 HTTP 标头 我正在使用 chrome webRequest API 来实现同样的目的 但我仍然无法阅读它 这是我的代码 chrome webRequest onBeforeSendHea
  • 复制 Http 请求输入流

    我正在实现一个代理操作方法 该方法转发传入的 Web 请求并将其转发到另一个网页 并添加一些标头 该操作方法适用于 GET 请求的文件 但我仍在努力转发传入的 POST 请求 问题是我不知道如何正确地将请求正文写入传出的 HTTP 请求流
  • 处置 RestRequest RestSharp 对象?

    我正在使用 RestSharp 并创建 RestRequest 对象以将 FileData 发送到 API 但是在得到响应后 我想从本地计算机中删除该文件 但是当我尝试执行相同操作时 它给了我错误 文件正在被其他进程使用 我认为的原因是我无
  • 使用 WebClient 和 WebRequest 之间的编码差异?

    在获取一些随机的西班牙报纸索引时 我没有使用 WebRequest 正确获取变音符号 它们产生了这个奇怪的字符 同时使用 a 从同一个 uri 下载响应WebClient我得到了适当的回应 为什么会出现这种差异化呢 var client n
  • c# httpwebrequest getResponse() 冻结并挂起我的程序

    我试图使用 httpwebrequest 在远程服务器上使用类似于休息的服务 从第一次执行本身开始 我的代码就挂起了程序 然后我尝试将它作为控制台应用程序 以确保它与程序本身无关 但没有运气 string credentialsJson u
  • C# - 如何进行 HTTP 调用

    我想对网站进行 HTTP 调用 我只需要点击 URL 不想上传或下载任何数据 最简单 最快的方法是什么 我尝试了下面的代码 但它很慢 并且在第二次重复请求后 它只是超时 59 秒 然后恢复 WebRequest webRequest Web

随机推荐