修改Chrome扩展程序的HTTP响应

cap*_*gon 62 google-chrome-extension

是否可以创建修改HTTP响应正文的Chrome扩展程序?

我查看了Chrome扩展API,但我没有找到任何可以执行此操作的内容.

Rob*_*b W 40

通常,您无法使用标准Chrome扩展程序API更改HTTP请求的响应正文.

104058请求此功能:WebRequest API:允许扩展来编辑响应正文.明星问题以获得更新通知.

如果要编辑已知的响应正文XMLHttpRequest,请通过内容脚本注入代码,以覆盖默认XMLHttpRequest构造函数,使用自定义(全功能)构造函数,在触发真实事件之前重写响应.确保您的XMLHttpRequest对象完全符合Chrome的内置XMLHttpRequest对象,否则AJAX密集的站点将会中断.

在其他情况下,您可以使用chrome.webRequestchrome.declarativeWebRequestAPI将请求重定向到data:-URI.与XHR方法不同,您不会获得请求的原始内容.实际上,请求永远不会命中服务器,因为重定向只能在发送实际请求之前完成.如果您重定向main_frame请求,用户将看到data:-URI而不是请求的URL.


dut*_*tzi 21

我刚刚发布了一个Devtools扩展,就是这样:)

它被称为篡改,它基于mitmproxy,它允许您查看当前选项卡发出的所有请求,修改它们并在下次刷新时提供修改后的版本.

这是一个非常早期的版本,但它应该与OS X和Windows兼容.如果它不适合你,请告诉我.

你可以在这里得到它http://dutzi.github.io/tamper/

这是如何工作的

正如@Xan在下面评论的那样,扩展通过Native Messaging与扩展mitmproxy的python脚本进行通信.

扩展名列出了所有使用的请求chrome.devtools.network.onRequestFinished.

当您单击请求时,它会使用请求对象的getContent()方法下载其响应,然后将该响应发送到本地保存的python脚本.

然后它在编辑器中打开文件(call用于OSX或subprocess.PopenWindows).

python脚本使用mitmproxy来侦听通过该代理进行的所有通信,如果它检测到对已保存文件的请求,则会为保存的文件提供服务.

我使用Chrome的代理API(特别是chrome.proxy.settings.set())将PAC设置为代理设置.该PAC文件将所有通信重定向到python脚本的代理.

有关mitmproxy的最大优点之一是它还可以修改HTTPs通信.所以你也有:)

  • 有趣的Devtools扩展!但是,似乎只能修改响应*标题*而不是使用Tamper修改响应*body*. (8认同)
  • 顺便说一下,如果你更好地解释这里使用的技术,这将有所帮助. (4认同)
  • 安装问题. (2认同)

Mul*_*er0 10

是.这是可能与chrome.debuggerAPI,授予到延伸访问铬DevTools协议,它支持HTTP截取过程和调整通过其网络API.

Chrome问题487422的评论建议使用此解决方案:

对于想要一个目前可行的替代方案的任何人,您可以chrome.debugger在后台/事件页面中使用以附加到您想要收听的特定选项卡(或者如果可能,则附加到所有选项卡,未亲自测试所有选项卡) ,然后使用调试协议的网络API.

唯一的问题是在标签的视口顶部会有通常的黄色条,除非用户将其关闭chrome://flags.

首先,将调试器附加到目标:

chrome.debugger.getTargets((targets) => {
    let target = /* Find the target. */;
    let debuggee = { targetId: target.id };

    chrome.debugger.attach(debuggee, "1.2", () => {
        // TODO
    });
});
Run Code Online (Sandbox Code Playgroud)

接下来,发送Network.setRequestInterceptionEnabled命令,这将启用拦截网络请求:

chrome.debugger.getTargets((targets) => {
    let target = /* Find the target. */;
    let debuggee = { targetId: target.id };

    chrome.debugger.attach(debuggee, "1.2", () => {
        chrome.debugger.sendCommand(debuggee, "Network.setRequestInterceptionEnabled", { enabled: true });
    });
});
Run Code Online (Sandbox Code Playgroud)

Chrome现在将开始发送Network.requestIntercepted活动.为他们添加一个监听器:

chrome.debugger.getTargets((targets) => {
    let target = /* Find the target. */;
    let debuggee = { targetId: target.id };

    chrome.debugger.attach(debuggee, "1.2", () => {
        chrome.debugger.sendCommand(debuggee, "Network.setRequestInterceptionEnabled", { enabled: true });
    });

    chrome.debugger.onEvent.addListener((source, method, params) => {
        if(source.targetId === target.id && method === "Network.requestIntercepted") {
            // TODO
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

在监听器中,params.request将是相应的Request对象.

发送回复Network.continueInterceptedRequest:

  • 传递所需HTTP原始响应的base64编码(包括HTTP状态行,标题等!)rawResponse.
  • 传递params.interceptionIdinterceptionId.

请注意,我根本没有测试过这些.


Mix*_*OID 9

就像@Rob w所说,我已经覆盖了XMLHttpRequest,这是修改任何站点中任何XHR请求的结果(类似于透明的修改代理):

var _open = XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function (method, URL) {
    var _onreadystatechange = this.onreadystatechange,
        _this = this;

    _this.onreadystatechange = function () {
        // catch only completed 'api/search/universal' requests
        if (_this.readyState === 4 && _this.status === 200 && ~URL.indexOf('api/search/universal')) {
            try {
                //////////////////////////////////////
                // THIS IS ACTIONS FOR YOUR REQUEST //
                //             EXAMPLE:             //
                //////////////////////////////////////
                var data = JSON.parse(_this.responseText); // {"fields": ["a","b"]}

                if (data.fields) {
                    data.fields.push('c','d');
                }

                // rewrite responseText
                Object.defineProperty(_this, 'responseText', {value: JSON.stringify(data)});
                /////////////// END //////////////////
            } catch (e) {}

            console.log('Caught! :)', method, URL/*, _this.responseText*/);
        }
        // call original callback
        if (_onreadystatechange) _onreadystatechange.apply(this, arguments);
    };

    // detect any onreadystatechange changing
    Object.defineProperty(this, "onreadystatechange", {
        get: function () {
            return _onreadystatechange;
        },
        set: function (value) {
            _onreadystatechange = value;
        }
    });

    return _open.apply(_this, arguments);
};
Run Code Online (Sandbox Code Playgroud)

例如,Tampermonkey可以成功使用此代码在任何站点上进行任何修改:)

  • 我已经使用了您的代码,并且它在控制台上记录了捕获的内容,但它并没有改变我的应用程序得到的响应(Angular)。 (2认同)
  • @AndréRoggeriCampos我遇到了同样的事情。Angular使用了较新的`response`而不是`responseText`,因此您要做的就是将Object.defineProperty更改为使用`response`。 (2认同)