CORS和网络扩展 [英] CORS and web extensions

查看:259
本文介绍了CORS和网络扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I set up a server on http://localhost:8080 where http://example.com can do POST requests :

'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:8080 来自 http:// localhost: 8081 由于相同的原始政策。

It works fine : I can't do a POST request to http://localhost:8080 from http://localhost:8081 because of the same origin policy.

然后,我为Firefox编写了一个Web扩展程序,该扩展程序将尝试对 http:// localhost:8080 来自任何域。

Then I wrote a web extension for Firefox that will try to do a POST request to http://localhost:8080 from any domain.

以下是其清单:

{
    "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 没有给予他的许可

What I don't understand is that it works. The extension do the request to http://localhost:8080 and Firefox didn't block it because the manifest allows it, however the server (http://locahost:8080) didn't give his permission.

推荐答案

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

Short version: CORS is a protocol for controlling the behavior of the browser, not the server. And your use of the addon permissions setting bypasses CORS.

如果您查看自己的CORS代码,则会看到它不做任何拒绝请求的事情;它只是在响应上设置标题。这些标头将指示浏览器客户端是否可以读取响应,但是无论如何都将发送响应。

If you look at your CORS code you'll see that it doesn't do anything to reject requests; it just sets headers on the response. Those headers will instruct the browser whether or not the client can read the response, but the response will be sent in any case.

这一事实可能会被某些请求所掩盖强制CORS飞行前检查。在这种情况下,浏览器首先发送一个特殊的 OPTIONS 请求,并且附加到该响应的标头可以阻止浏览器发送实际请求。这是一种向后兼容机制,不适用于所有请求。 (请参见此答案

This fact can be obscured by certain requests that force CORS preflights. In that case, the browser first sends a special OPTIONS request, and the headers attached to that response can keep the browser from sending the real request. This is a backwards-compatibility mechanism that doesn't apply to all requests. (See this answer for a longer explanation.)

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

That's what's happening in your example. Your POST is of a type that requires a preflight check under CORS. So in the regular version, the browser sends a preflight check, sees the response headers, and doesn't bother to send the real request. But if it had been a different kind of POST it would have sent the request directly, and the server would have executed it.

在插件版本中,您明确允许您的权限设置中的域。此绕过CORS

In the addon version, you specifically allowed this domain in your permissions setting. This bypasses CORS:


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

The extra privileges include: XMLHttpRequest and fetch access to those origins without cross-origin restrictions (even for requests made from content scripts).

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

So in this case the preflight isn't required and the request is sent directly.

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

If you want to reject requests on the server that come from certain domains (or protect against CSRF more generally), there will be other settings for that. What they are depends on your web framework.

这篇关于CORS和网络扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆