CORS Chrome扩展程序,使用清单版本2

30

在编写谷歌浏览器扩展程序时,是否可以使用CORS?

我看到了这个链接, http://developer.chrome.com/extensions/contentSecurityPolicy.html

我试图将以下内容插入到清单中, "content_security_policy": "script-src 'self' https://twitter.com/; object-src 'self'",

但是一个ajax请求失败了,并显示以下错误信息: XMLHttpRequest无法加载https://twitter.com/。起源chrome-extension://olimhkjfpndfhdopbneamnekfalckinc不被Access-Control-Allow-Origin允许。


2
内容安全策略(CSP)和跨域资源共享(CORS)是完全不同的。CSP 是客户端阻止同源策略允许的事物(如加载 <script>)的一种方式。CORS 则是服务器允许被阻止的事物(即跨域 Ajax)的一种方式。 - apsillers
5个回答

46

为了让你的扩展程序能够从Twitter进行跨域Ajax请求,你只需要在你的清单文件中将Twitter列为主机权限即可:

...
"permissions": [
    "*://*.twitter.com/*"
],
...

2
在Chrome 76中,我的权限很好。但是在Chrome 77中,该权限不允许CORS。 - gumuruh
2022年不再工作。 - Shiv Singh
4
这仍然是有效的匹配模式,允许从特定主机获取内容;然而,现代扩展只允许从后台页面进行跨域请求。如果您尝试在内容脚本中进行跨域请求,无论权限如何,Chrome都会阻止它。(您需要在后台页面进行获取,并通过扩展消息传递与内容脚本通信。)此外,清单v3只允许fetch,而不允许XMLHttpRequest - apsillers
是的,正在处理后台工作。 - Shiv Singh
8
v3清单的更新中"host_permissions": ["https://*/"]的意思是允许扩展程序在所有以"https://"开头的网站上运行。 - Anton Toshik
@apsillers,您知道在MV3中从后台(Service Worker)获取特定主机的情况下需要什么样的主机权限吗?我正在进行一些测试,看起来即使没有任何主机权限,fetch也可以正常工作。 - pkacprzak

40
更新 2023-11-18:这一切都适用于 "manifest_version": 2,尽管谷歌一直威胁要拒绝它,但我仍然在使用它。主要是因为 v3 没有 .getPackageDirectoryEntry(),这意味着我无法监听我的文件并进行热重载。所以我希望在我不得不切换之前他们会把它加回来(或类似的功能)。
解释:
从 Chrome 73 开始,跨站点请求被阻止。 (即使您在权限属性中拥有这些主机。) 一些网站似乎可以通过未被阻止,但我相信最终大多数网站都会被阻止。
您必须在后台页面中发起请求...

设置

在您的manifest.json中添加一个部分,指向背景页面。 如果您正在使用manifest v3,则需要在此处使用service_worker属性,而不是scripts

"background": {
  "scripts": ["bg_page.js"],
  "persistent": false
}

创建背景页面:bg_page.js
chrome.runtime.onMessage.addListener(
    function(url, sender, onSuccess) {
        fetch(url)
            .then(response => response.text())
            .then(responseText => onSuccess(responseText))
        
        return true;  // Will respond asynchronously.
    }
);

然后在 main.js 中使用它。
chrome.runtime.sendMessage( //goes to bg_page.js
      url,
      data => dataProcessFunction(data) //your callback
); 

额外提示

如果你在背景页中执行类似console.log()的操作,点击Chrome扩展管理器中你的扩展方块中的“检查视图背景页”链接,你将会得到一个独立的开发工具窗口,用于查看背景页的所有操作。

如果你想自己查看文档:


@The.Wolfgang.Grimmer - 不确定,从未涉及过browserActions。您可以通过在popup.html中创建一个按钮来调用后台页面中的同一函数进行测试。或者,如果您尚未设置后台页面,则该按钮可以仅调用后台页面中的一个函数,该函数仅执行控制台日志记录。(只需确保在“检查视图后台页面”下检查它即可。) - Brad
我不得不将这个答案与添加原点作为权限(如被接受的答案中建议的那样)结合起来 - 两者一起解决了问题。 - Bert H
1
但是难道不需要在清单中为跨站点请求URL定义权限吗?类似于“permissions”:[“https://www.someurl.com/*”,...]。我已经发布了一个相关问题:https://stackoverflow.com/questions/67106588/cross-site-requests-from-background-script-works-even-if-not-allowed-in-manifest - Axel Stone
1
作为另一个猜测,Google可能会因为与您的权限URL相关的某个自动批准流程看到它没有受限制并判断您的权限“过度”,而拒绝了您的清单和权限部分。至于为什么Bert H需要两者,我不确定。希望这可以帮助到您。 - Brad
1
"无法在manifest_version 3中使用“background.scripts”键。请改用“background.service_worker”键。" - user3064538
显示剩余4条评论

5

Manifest V3 更新


我找到了一种方法来实现这个。但请务必非常小心地进行url过滤和其他安全保护措施。

在 Manifest v3 中,您可以设置规则来修改进出站调用。在清单的一个新部分 "host_permissions" 中包含您正在请求的站点名称。您可以在此处查看如何在清单中实现规则: https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#manifest

有一个名为 "allowAllRequests" 的规则动作,使用此规则可以让您进行跨域请求,绕过预检查。您可以在此处阅读更多关于规则的内容: https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#type-RuleActionType

要使用此规则,您需要在 "condition" 中包含 "resourceTypes" 密钥,并提供值 "main_frame""sub_frame"

同时,请确保完全卸载您的扩展程序并重新安装它,以便使这些更改生效。


谷歌的示例清单:

{
  "name": "My extension",
  ...

  "declarative_net_request" : {
    "rule_resources" : [{
      "id": "ruleset_1",
      "enabled": true,
      "path": "rules_1.json"
    }, {
      "id": "ruleset_2",
      "enabled": false,
      "path": "rules_2.json"
    }]
  },
  "permissions": [
    "declarativeNetRequest",
    "declarativeNetRequestFeedback",
    "*://example.com/*"
  ],
  "host_permissions": [
    "http://www.blogger.com/",
    "*://*/*"
  ],
  ...
}

示例 Rule.json:

[
    {
        "id": 1,
        "priority": 1,
        "action": { "type": "allowAllRequests" },
        "condition": {
            "urlFilter": "again make sure you are very specific with this.",
            "resourceTypes": ["main_frame"]
        }
    }
]

2
对于V3,您只需要添加:
"host_permissions": ["https://*/"]

你需要删除你的扩展程序,而不是重新加载。然后再次添加即可。 =)

0

对于 Manifest V3,这个方法对我有效。

  "host_permissions": [
    "https://api.jdoodle.com/v1/execute",
    "*://*/*"
  ],

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接