CORS和网络扩展

时间:2018-10-27 17:57:05

标签: firefox-addon same-origin-policy

我在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:8080http://localhost:8081发出POST请求。

然后,我为Firefox编写了一个Web扩展程序,它将尝试从任何域向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未给予他的许可

1 个答案:

答案 0 :(得分:2)

简短版本:CORS是用于控制浏览器(而非服务器)行为的协议。而您对插件permissions设置的使用会绕过CORS。

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

某些强制CORS起飞前的要求可能会掩盖这一事实。在这种情况下,浏览器首先发送一个特殊的OPTIONS请求,并且附加到该响应的标头可以阻止浏览器发送实际请求。这是一种向后兼容机制,不适用于所有请求。 (有关详细说明,请参见this answer。)

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

在插件版本中,您专门在permissions设置中允许此域。 bypasses CORS

  

额外的特权包括:XMLHttpRequest和获取对这些源的访问,而没有跨域限制(即使对于内容脚本发出的请求也是如此)。

因此,在这种情况下,不需要进行飞行前检查,而是直接发送请求。

如果您要拒绝来自某些域的服务器上的请求(或者更一般地抵御CSRF),则将有其他设置。它们是什么取决于您的Web框架。