如何进行从(纽约)网页到 Chrome 扩展程序的安全通信

How to do secure communication from a(ny) web page to a Chrome extension

我想在网页与 Chrome 扩展程序之间进行安全通信。经过相当多的检查和黑客攻击,这似乎至少是不平凡的,如果不是完全不可能的话。

我想从网页中的(某些 JavaScript)向扩展程序的后台页面(虽然它是 运行)发送消息(请注意,网页启动通信,这很不典型!)。我向扩展程序发送了一些凭据(因此需要安全通道!),然后如果这些凭据有效(由后台页面中的逻辑确定),那么后台页面应该 return 一些(JSON ) 值,然后网页可以显示这些值。

我已经有一些代码可以检查当前浏览器是否为 Chrome 以及用户是否安装了所述扩展(如果 him/her 有一些 UI 安装它它不是,等等...)

我还使用 window.postMessage 进行了一些交流 运行。它从网页脚本向自己发布消息到扩展内容脚本,然后从那里传播到后台页面。然而,这并不安全,因为 this MDN page 引用:

.. it is recommended that postMessage not be used to communicate with chrome: pages for now; use a different method (such as a query string when the window is opened) to communicate with Chrome windows.

(此评论位于页面底部附近的 Using window.postMessage in extensions 部分)

这似乎是一个合理的建议,因为似乎没有办法排除使用 postMessage 发送的数据可能被浏览器中的另一个 window/tab 拦截的可能性,而不是到达扩展程序。所以这个漏洞可以被利用。

在我的情况下,使用 MDN 文章建议的查询字符串是不可能的,因为后台页面是在开始时加载的(还没有 URL 参数)。

我的推理是sound/clear吗?有没有Chrome扩展专家有什么建议?

注意:建议使用 externally_connectable docs,但如 docs 中所述,用于指定网站的 matches 部分仅允许子域通配符,问题域需要允许动态网站列表,不能在扩展的清单中进行硬编码。

您需要使用"externally_connectable"沟通方式。

如果您的扩展程序声明它想要与某个域(您需要在清单中列出)进行通信,那么 chrome.runtime.sendMessage 将暴露给页面上下文。

然后,在您的页面上,您可以通过以下方式传递信息:

var extensionID = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

if(chrome && chrome.runtime && chrome.runtime.sendMessage) {
  // There is an extension that declared this page in externally_connectable
  chrome.runtime.sendMessage(extensionID, data);
} else {
  // Either this is not Chrome, or no extension wants to listen
}

在扩展端,您将获得 chrome.runtime.onMessageExternal event 中的数据。

如果您愿意,您可以与 chrome.runtime.connect 建立双向长期连接。

Chrome 将确保只有具有给定 ID 的分机才能收到您的消息。这将保护您免受 其他网页 的窃听,但请注意任何 扩展程序 都可以有足够的能力附加到/修改您页面的脚本和获取该数据。


由于问题已根据 "no fixed list of sites" 要求更新,因此有一个替代解决方案。内容脚本可以使用 DOM 事件与页面脚本通信。它们不会泄漏到其他页面,但同样,这不能防止其他扩展。

有关详细信息,请参阅 this answer;我将在此处留下一个代码片段作为示例。

// Content script
//Listen for the event
window.addEventListener("PassToBackground", function(evt) {
  chrome.runtime.sendMessage(evt.detail);
}, false);

// Page context
var message = {/* whatever */};
var event = new CustomEvent("PassToBackground", {detail: message});
window.dispatchEvent(event);