Chrome 扩展 XHR 收到 403 响应,除非从 file:/// 启动

Posted

技术标签:

【中文标题】Chrome 扩展 XHR 收到 403 响应,除非从 file:/// 启动【英文标题】:Chrome Extension XHR receives 403 response except when initiated from file:/// 【发布时间】:2018-03-19 17:04:46 【问题描述】:

我正在开发一个 Chrome 扩展程序,它利用 fixer.io API 获取货币汇率。

我通过一个简单的 html 页面开发扩展,其中通过 <script> 标签包含我的 javascript。当我想实时测试它时,我会构建它,转到 chrome://extensions 并单击 Load unpacked extension

每当我从简单的 HTML 开发页面向 API 发出请求时,一切正常。但是,当我构建扩展程序并通过内容脚本发出请求时,我会收到来自 API 的 403 响应。

马上,我要说我的 manifest.json 中有这些权限:

"permissions": [
  "https://*/*",
  "http://*/*"
]

这是我加载脚本的方式(按照 Makyen 的要求):

"content_scripts": [
  
    "run_at": "document_start",
    "css": [
      "main.css"
    ],
    "js": [
      "script.js"
    ],
    "matches": [
      "file:///*",
      "http://*/*",
      "https://*/*"
    ]
  
]

如果我将请求更改为另一个(虚拟)API:

https://jsonplaceholder.typicode.com/posts?base=USD

一切都在任何地方都有效,这意味着问题不在我的扩展设置中。

有问题的请求是这样的:

https://api.fixer.io/latest?base=USD

它给出了错误:

GET https://api.fixer.io/latest?base=USD 403 (Forbidden)

下面是初始化请求的代码:

function currencyAPICall(currency, callback) 
    var url = "https://api.fixer.io/latest?base=" + currency,
        req = new XMLHttpRequest();

    req.addEventListener("load", function () 
        callback(data.rates);
    );

    req.open("GET", url, true);
    req.send(null);

    return req;


为了测试这一点,我让我的扩展在我的开发 HTML 文件中运行在文件 URL 上。 IE。相同的代码运行两次,一次来自我的 HTML 页面,一次来自扩展。结果如下:

除了使用file 协议外,我的扩展在任何地方都会收到 403。它是否在 localhost、*** 甚至 fixer.io 网站本身上运行都没关系。请求使用https

求和

扩展内容脚本在任何地方都会收到来自 API 调用的 403 响应,除非在使用 file 协议的页面上运行,即使具有正确的清单权限也是如此。 为什么?

如果我向另一个 URL(上述虚拟 API)发出请求,我不会收到此错误。这是否意味着问题出在 fixer.io 服务器上?或者我需要设置某种标题?

我还在 fixer.io 的 GitHub 存储库上写了一个 issue 关于这个。

编辑:

我注意到的主要区别之一是 OriginReferer 标头。如果两者都设置或两者都未设置,则响应似乎为 200。当我收到 403 响应时,Referer 已设置,但 Origin 未设置。

编辑:

根据 PredatorIWD 的建议,从 Event Page(又名背景页面)发出请求不会导致 403。我得到正常的 200 OK 响应。

【问题讨论】:

如果您从扩展 HTML 文件发送请求,那么您需要将其添加到 web_accessible_resources。从background.js 发送请求并使用消息传递将所需数据发送回内容脚本通常也更好。并且源头是浏览器自动添加的,用户无法控制。 web_accessible_resources 在这种情况下不会做任何事情,因为“内容脚本本身不需要列入白名单。”但是,在事件(后台)页面中发出请求不会导致 403。我可能只是更改我的代码以利用它。 请edit 成为主题的问题:包括一个minimal reproducible example 重复问题。对于 Chrome 扩展程序或 Firefox WebExtensions,您几乎总是需要包含您的 manifest.json 和一些背景、内容和/或弹出脚本/HTML,通常是网页 HTML/脚本。寻求调试帮助的问题(“为什么我的代码没有按我想要的方式工作?”)必须包括:(1)期望的行为,(2)特定的问题或错误以及(3)重现它所需的最短代码在问题本身中。另请参阅:What topics can I ask about here? 和 How to Ask。 您已将关键信息排除在问题之外。 Chrome 扩展程序在多个不同的上下文中运行代码。我们需要看看您是如何加载代码的。因此,一个 manifest.json 显示内容和背景脚本条目(permissionsbrowser_action/page_action)以及来自各种不同脚本和 HTML 的尽可能多的代码,为我们提供完整,但最小的 MCVE 会重复问题。 @PredatorIWD 您应该将该评论写为答案,以便我将其标记为正确。我最终在事件页面中移动了我的请求,问题就消失了。 【参考方案1】:

就像我在评论中所说,通常最好从background.js 发送请求并使用消息传递将所需数据发送回内容脚本。

下面是从后台脚本到内容脚本的简单一次性消息示例:

来自后台脚本:

chrome.tabs.query(active: true, currentWindow: true, function(tabs) 
    chrome.tabs.sendMessage(tabs[0].id, greeting: "hello", function(response) 
        console.log(response.farewell);
    );
);

到内容脚本:

chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) 
    if (request.greeting == "hello")
        sendResponse(farewell: "goodbye");
    
);

您可以阅读有关消息传递的更多信息here。

【讨论】:

以上是关于Chrome 扩展 XHR 收到 403 响应,除非从 file:/// 启动的主要内容,如果未能解决你的问题,请参考以下文章

从 Chrome 扩展程序获取请求导致 403 Forbidden

如何在 HTTP 403 响应中获取自定义错误响应文本

在 Chrome 中的 XHR 中设置断点

在 Chrome 中的 XHR 中设置断点

“未经检查的 runtime.lastError:消息端口在收到响应之前关闭。” Chrome 扩展程序

Chrome 扩展错误“未检查的 runtime.lastError:消息端口在收到响应之前关闭”