【问题标题】:Firefox extension: Cancel requests and emit fake responsesFirefox 扩展:取消请求并发出虚假响应
【发布时间】:2011-08-28 17:25:25
【问题描述】:

我正在尝试开发一个 Firefox 扩展,它将每个 HTTP 请求丢弃到某个站点并返回一个虚假响应。任何请求都不应通过原始 Web 服务器,但我希望能够创建自定义响应。我试图拦截“http-on-modify-request”消息,但取消请求似乎不起作用,因为之后我无法模拟真正的响应。同样,使用 nsITraceableStream 实例,我似乎无法真正取消请求。我没有想法,有人可以帮忙吗?

【问题讨论】:

  • 这个扩展的用途是什么?
  • 也许你想看看 LeechBlock 如何阻止请求:addons.mozilla.org/en-US/firefox/addon/leechblock
  • @Felix:我知道如何阻止请求,但如果我按照通常的方式(对“http-on-modify-request”消息做出反应),我无法伪造响应。
  • @Amir:我们(我工作的一家 IT 安全公司)希望将它用于演示目的,以展示当您可以访问客户端(浏览器)。
  • @Niklas:为什么不直接使用 Fiddler (www.fiddler2.com) AutoResponder 来执行此操作?然后,您可以在所有浏览器中进行演示。

标签: javascript http firefox firefox-addon xpcom


【解决方案1】:

自 Firefox 21 起,以下答案已被取代,现在 nsIHttpChannel.redirectTo() method 可以很好地完成这项工作。你可以重定向到一个 data: URI,这样就可以了:

Components.utils.import("resource://gre/modules/Services.jsm");
const Ci = Components.interfaces;

[...]

onModifyRequest: function(channel)
{
  if (channel instanceof Ci.nsIHttpChannel && shouldRedirect(channel.URI.spec))
  {
    let redirectURL = "data:text/html," + encodeURIComponent("<html>Hi there!</html>");
    channel.redirectTo(Services.io.newURI(redirectURI, null, null));
  }
}

原始答案(过时)

每个通道都有其关联的stream listener,当接收到数据时会收到通知。要伪造响应,您需要做的就是获取此侦听器并为其提供错误的数据。而nsITraceableChannel 实际上就是这样做的方法。您需要自己替换频道的通常侦听器,该侦听器不会做任何事情,之后您可以取消频道而不会通知侦听器。然后你触发监听器并给它你自己的数据。像这样的:

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
const Cc = Components.classes;
const Ci = Components.interfaces;

[...]

onModifyRequest: function(channel)
{
  if (channel instanceof Ci.nsIHttpChannel && channel instanceof Ci.nsITraceableChannel)
  {
    // Our own listener for the channel
    var fakeListener = {
      QueryInterface: XPCOMUtils.generateQI([Ci.nsIStreamListener,
                        Ci.nsIRequestObserver, Ci.nsIRunnable]),
      oldListener: null,
      run: function()
      {
        // Replace old listener by our fake listener
        this.oldListener = channel.setNewListener(this);

        // Now we can cancel the channel, listener old won't notice
        //channel.cancel(Components.results.NS_BINDING_ABORTED);
      },
      onDataAvailable: function(){},
      onStartRequest: function(){},
      onStopRequest: function(request, context, status)
      {
        // Call old listener with our data and set "response" headers
        var stream = Cc["@mozilla.org/io/string-input-stream;1"]
                       .createInstance(Ci.nsIStringInputStream);
        stream.setData("<html>Hi there!</html>", -1);
        this.oldListener.onStartRequest(channel, context);
        channel.setResponseHeader("Refresh", "5; url=http://google.com/", false);
        this.oldListener.onDataAvailable(channel, context, stream, 0, stream.available());
        this.oldListener.onStopRequest(channel, context, Components.results.NS_OK);
      }
    }

    // We cannot replace the listener right now, see
    // https://bugzilla.mozilla.org/show_bug.cgi?id=646370.
    // Do it asynchronously instead.
    var threadManager = Cc["@mozilla.org/thread-manager;1"]
                          .getService(Ci.nsIThreadManager);
    threadManager.currentThread.dispatch(fakeListener, Ci.nsIEventTarget.DISPATCH_NORMAL);
  }
}

这段代码的问题仍然是如果频道被取消,页面仍然显示为空白(所以我评论了那行) - 听众似乎仍在查看频道并注意到它被取消了。

【讨论】:

  • 谢谢弗拉基米尔,我去看看!
  • 您好,Wladimir,我在 Firefox 6 中尝试了您的代码,并在 oldListener.onStartRequest(channel, oldContext); 上尝试了 FiFo 段错误我现在将尝试 FiFo 3.5 以确保。实际上,我使用了一种非常相似的方法来处理空侦听器,但在 onExamineResponse 中,我似乎无法取消请求并设置任何响应标头。
  • @Niklas:这可能是因为此时尚未设置 oldContext,因此您使用错误的上下文调用它 - 我猜该通道是异步取消的,这意味着 onStopRequest被称为太晚了。将所有伪造请求的代码 (onStartRequest & Co.) 移动到您的虚假侦听器的 onStopRequest 中应该可以解决此问题。
  • 我已经有了这个想法并尝试了this 代码,但没有调用 fakeListener 中的任何警报。但是,alert("Registering fake listener...") 被调用。 编辑: 当我 not 取消请求时,甚至不会调用假侦听器。
  • @Niklas:在网络代码中调用alert() 是个坏主意,并且可能由于某种原因无法正常工作(它会产生一个模态对话框)。您应该使用Components.utils.reportError()window.dump(),它们会产生更可靠的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-18
  • 1970-01-01
相关资源
最近更新 更多