NodeJS Firebase函数CORS错误访问控制允许原点

w51jfk4q  于 2022-11-29  发布在  Node.js
关注(0)|答案(1)|浏览(156)

我有一个简单的firebase函数,它返回hello world

exports.myFunc = functions
    .runWith({
        maxInstances: 1,
        memory: "128MB"
    })
    .https.onRequest(async (request, response) => {
        response.set("Content-Type", "text/plain");
        response.status(200).send('Hello world!');
    }

我用一个POST请求调用它,该请求包含以下头:

>  {
>    host: 'localhost:5001',
>    connection: 'keep-alive',
>    pragma: 'no-cache',
>    'cache-control': 'no-cache',
>    accept: '*/*',
>    'access-control-request-method': 'POST',
>    'access-control-request-headers': 'authorization,content-type',
>    origin: 'http://localhost:8080',
>    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
>    'sec-fetch-mode': 'cors',
>    'sec-fetch-site': 'same-site',
>    'sec-fetch-dest': 'empty',
>    referer: 'http://localhost:8080/',
>    'accept-encoding': 'gzip, deflate, br',
>    'accept-language': 'en-US,en;q=0.9'
>  }

问题是当我尝试调用CORS时遇到了错误,因为我是从firebase上托管的vue应用程序调用它的。好吧,这是有道理的,所以我读了一些关于CORS的文档,它抛出的第一个错误是:

from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

好的,我添加所需的标题:

exports.myFunc = functions
    .runWith({
        maxInstances: 1,
        memory: "128MB"
    })
    .https.onRequest(async (request, response) => {
        if (request.method === 'OPTIONS') {
            response.set('Access-Control-Allow-Origin', '*');
            response.status(204).send('');
        } else {
            // return hello world 
        }
    }

我知道允许all(*)是一个不好的安全实践,并且违背了CORS的一些目的,但是这是为了测试。使用上面的设置,我得到了另一个CORS错误:

from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.

好的,我再添加一些标题:

exports.myFunc = functions
    .runWith({
        maxInstances: 1,
        memory: "128MB"
    })
    .https.onRequest(async (request, response) => {
        if (request.method === 'OPTIONS') {
            response.set('Access-Control-Allow-Headers', "authorization,content-type");
            response.set('Access-Control-Allow-Origin', '*');
            response.status(204).send('');
        } else {
            // return hello world 
        }
    }

但添加该标题给我同样的错误从第一!:

from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

我已经尝试了所有的随机头组合,auth头,凭证头,启用所有的头方法,等等。没有组合似乎工作我做错了什么?我在网上找到的所有答案都告诉我添加

'Access-Control-Allow-Origin', '*'

是解决方案,但它不工作?一个解决方案导致另一个错误,等等。
下面是我返回的返回头:

>  [Object: null prototype] {
>    'x-powered-by': 'Express',
>    'access-control-allow-headers': 'authorization,content-type',
>    'access-control-allow-origin': '*'
>  }
mqkwyuun

mqkwyuun1#

所以我找出了原因,是很多事情出了问题,希望这对将来和我一样犯同样错误的人有帮助。
1.在处理CORS时,您需要确保在初始CORS预检请求和THE ACTUAL REQUEST THAT COES AFTER的响应中发送所需的标题。在我的案例中,我返回的是选项预检请求的正确标题,而不是后面的实际请求。
1.如果您使用chrome进行调试,您可以将开发者控制台设置为同时显示预检请求和实际请求。我的chrome版本与这两个请求结合在一起这让我一直相信是预检仍然导致了问题。您可以按照以下答案更改chrome设置:Chrome not showing OPTIONS requests in Network tab
1.最后,修复过程非常简单,只需在实际请求中再次添加所需的cors头即可修复所有问题。代码如下:

.https.onRequest(async (request, response) => {

     if (request.method === 'OPTIONS') {
         response.set('Access-Control-Allow-Headers', "authorization,content-type");
         response.set('Access-Control-Allow-Origin', '*');
         response.status(204).send('');
     } 
     else {
         // return hello world 
         response.set('Access-Control-Allow-Origin', '*');
     }

请注意,响应现在还将返回访问控制允许源标头,而不管它是预检选项请求还是实际请求。

相关问题