Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
718 views
in Technique[技术] by (71.8m points)

cors - CORS和网络扩展(CORS and web extensions)

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

(我在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));

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

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

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

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

Here is its manifest :

(这是它的清单:)

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

and its content-script.js code :

(及其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'}));

})();

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 .

(该扩展程序将请求发送到http:// localhost:8080 ,Firefox并未阻止它,因为清单允许它,但是服务器( http:// locahost:8080没有给予他许可 。)

  ask by Cl00e9ment translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Short version: CORS is a protocol for controlling the behavior of the browser, not the server.

(简短版:CORS是用于控制浏览器而非服务器行为的协议。)

And your use of the addon permissions setting bypasses CORS.

(您对插件permissions设置的使用会绕过CORS。)

If you look at your CORS code you'll see that it doesn't do anything to reject requests;

(如果查看您的CORS代码,您会发现它对拒绝请求没有任何作用。)

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.

(这些标头将指示浏览器客户端是否可以读取响应,但是无论如何都将发送响应。)

This fact can be obscured by certain requests that force CORS preflights.

(强制执行CORS预检的某些请求可能会掩盖这一事实。)

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.

(在这种情况下,浏览器首先发送一个特殊的OPTIONS请求,并且附加到该响应的标头可以阻止浏览器发送实际请求。)

This is a backwards-compatibility mechanism that doesn't apply to all requests.

(这是一种向后兼容机制,不适用于所有请求。)

(See this answer for a longer explanation.)

((有关详细说明,请参见此答案 。))

That's what's happening in your example.

(这就是您的示例中发生的事情。)

Your POST is of a type that requires a preflight check under CORS.

(您的POST是需要在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.

(但是,如果它是另一种类型的POST,它将直接发送请求,而服务器将执行该请求。)

In the addon version, you specifically allowed this domain in your permissions setting.

(在插件版本中,您在permissions设置中明确允许此域。)

This bypasses CORS :

(这绕过了CORS :)

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

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

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

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

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.

(如果要拒绝来自某些域的服务器上的请求(或更一般地防止CSRF),则将有其他设置。)

What they are depends on your web framework.

(它们是什么取决于您的Web框架。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...