【问题标题】:CORS and web extensionsCORS 和网络扩展
【发布时间】:2019-04-01 03:51:24
【问题描述】:

我在http://localhost:8080 上设置了一个服务器,http://example.com 可以进行 POST 请求:

'use strict';

const express = require('express');

const app = express();
const port = 8080;

// allowing CORS for example.com
app.use('/', function (req, res, next) {
    res.header('Access-Control-Allow-Origin', 'http://example.com');
    if (req.method === 'OPTIONS') {
        res.header('Access-Control-Allow-Methods', 'OPTIONS, POST');
        res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length');
        res.status(200).send();
    } else {
        next();
    }
});

// handling POST requests
app.use('/', function (req, res) {
    console.log('a client did a POST request');
    res.status(200);
});

app.listen(port, () => console.log ('server started on port ' + port));

它工作正常:由于相同的来源策略,我无法从 http://localhost:8081http://localhost:8080 发出 POST 请求。

然后我为 Firefox 编写了一个网络扩展,它将尝试从任何域向http://localhost:8080 发出 POST 请求。

这是它的清单:

{
    "manifest_version" : 2,
    "name" : "aBasicExtension",
    "version" : "0.0.0",
    "content_scripts" : [
        {
            "matches" : ["<all_urls>"],
            "js" : ["content-script.js"]
        }
    ],
    "permissions" : ["*://*.localhost/*"]
}

及其content-script.js 代码:

(() => {

    'use strict';

    const xhr = new XMLHttpRequest();

    xhr.open('POST', 'http://localhost:8080');
    xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');

    xhr.addEventListener('readystatechange', () => {
        if (xhr.readyState === XMLHttpRequest.DONE){
            if (xhr.status === 200) console.log('OK');
            else console.error('an error has occured : ' + xhr.status);
        }
    });

    xhr.send(JSON.stringify({dataName: 'some data here'}));

})();

我不明白的是它有效。扩展程序向http://localhost:8080 发出请求,Firefox 没有阻止它,因为清单允许它,但是服务器 (http://locahost:8080) 没有给予他的许可

【问题讨论】:

    标签: cors firefox-addon same-origin-policy


    【解决方案1】:

    短版:CORS 是一种用于控制浏览器行为的协议,而不是服务器。并且您使用插件 permissions 设置绕过了 CORS。

    如果您查看您的 CORS 代码,您会发现它对拒绝请求没有任何作用;它只是在响应上设置标题。这些标头将指示浏览器客户端是否可以读取响应,但无论如何都会发送响应。

    某些强制 CORS 预检的请求可能会掩盖这一事实。在这种情况下,浏览器首先发送一个特殊的OPTIONS 请求,附加到该响应的标头可以阻止浏览器发送真正的请求。这是一种向后兼容机制,不适用于所有请求。 (更多解释请参见this answer。)

    这就是您的示例中发生的情况。您的 POST 属于需要在 CORS 下进行预检检查的类型。因此,在常规版本中,浏览器会发送预检检查,查看响应标头,并且不会费心发送真正的请求。但如果它是另一种类型的 POST,它会直接发送请求,并且服务器会执行它。

    在插件版本中,您在 permissions 设置中明确允许此域。这个bypasses CORS

    额外的权限包括:XMLHttpRequest 和 fetch 访问这些来源,没有跨域限制(即使是从内容脚本发出的请求)。

    所以在这种情况下不需要预检,直接发送请求。

    如果你想拒绝服务器上来自某些域的请求(或者更一般地防止 CSRF),会有其他设置。它们是什么取决于您的网络框架。

    【讨论】:

    • 非常感谢您的详细解释。这种行为是安全问题吗?事实上,如果我写了一个邪恶的插件,当你浏览你的邮件网站时,它会向我的服务器发出请求。本网站的 cookie 将被发送到我的服务器。我是否应该断定内容脚本发送的 xhr 不会包含网站 cookie?
    • @Cl00e9ment:我对 Firefox 插件一无所知,因此您可能应该单独询问该特定问题。但总的来说,是的,插件具有扩展的功能,允许它们做坏事。这就是为什么用户必须明确选择安装它们,并同意给予他们特定的权限。
    • 我刚刚测试过,不,当内容脚本执行 xhr 时,不会发送网站 cookie。这就解释了为什么插件可以绕过同源策略。
    猜你喜欢
    • 2016-07-15
    • 2014-07-26
    • 2023-01-30
    • 1970-01-01
    • 1970-01-01
    • 2020-05-02
    • 1970-01-01
    • 2018-12-24
    • 2021-08-22
    相关资源
    最近更新 更多