繁体   English   中英

Firebase 可调用 Function + CORS

[英]Firebase Callable Function + CORS

我正在尝试从我的应用程序调用可调用云 Function,但我面临 CORS 问题。 在此处输入图像描述

我无法启用 Cors,因为我无法访问 onCall function 上的请求和响应。这是我的 function:

exports.UserInvitation = functions.https.onCall((data, context) => {
  const email = data.email


  return new Promise((resolve, reject) => {
    admin.auth().createUser({
      email: email,
      emailVerified: false,
      password: password
    }).then(resolve).catch((err) => {
      console.error(err.code)
      reject(new functions.https.HttpsError(err.code, err.message))
    })
  })
})

这就是我的称呼:

functions.httpsCallable('UserInvitation')({ email: this.input.value }).then((data) => {
      console.log('Sent invitation:', data)
})

Firebase 函数 package.json:

{
  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "scripts": {
    "serve": "firebase serve --only functions",
    "shell": "firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "dependencies": {
    "bluebird": "^3.5.1",
    "firebase-admin": "~5.12.0",
    "firebase-functions": "^1.0.1"
  },
  "private": true
}

WEB SDK Firebase 版本:4.13.1

对于来到这里搜索 firebase 可调用函数 cors 错误的其他人,这是我的清单:

  1. 确保已部署该功能。
  2. 确保函数名称正确。 当它应该是recalculatY时,我正在调用recalculateY 由于某种原因出现 cors 错误。
  3. 确保函数代码本身没有抛出错误。 使用模拟器来帮助。 这并没有引发 cors 错误仍然有助于了解。
  4. 确保您的地区匹配 - 我正在使用europe-west2 我必须在该区域中部署该功能,并使用该区域调用它。 有一段时间,我认为如果函数名称正确,客户端会推断出正确的区域。 情况并非如此。

将可调用函数部署到特定区域:

// This is the file in which you define your callable function.
const functions = require('firebase-functions');
...
exports.yourFunc = functions.region('europe-west2').https.onCall(async (data, context) => {
    ...
})

从客户端调用特定区域中的函数(在本例中为 vuejs Web 应用程序):

// In my case, this is a vuex store file, but it is safe to assume this is plain old javascript
import firebase from 'firebase/app'
import 'firebase/functions'
...
firebase.app().functions('europe-west2').httpsCallable('yourFunc')

注意: firebase.app().function... vs firebase.app.function...

对于任何在 2020 年 1 月看这篇文章的人..

在 Reddit 上找到了这个答案( https://www.reddit.com/r/reactjs/comments/fsw405/firebase_cloud_functions_cors_policy_error/

结果是在 2020 年 1 月 15 日,Google 更改了安全设置,所有新功能都不再具有 Cloud Functions Invoker。 这意味着所有新创建的函数都将被禁止访问,从而导致 CORS 策略阻止。

这是您修复它的方法,因为它并不那么明显:

https://cloud.google.com/functions/docs/securing/managing-access-iam#allowing_unauthenticated_function_invocation

我的某些 Firebase 函数遇到了这个问题,但其他函数没有。 我最终通过这样做来修复它:

  1. 在 index.js 中注释掉函数
  2. 运行 Firebase 部署
  3. 在提示符下输入 y 以删除函数
  4. 等待 5 到 10 分钟
  5. 删除函数周围的注释并再次运行 firebase deploy

没有对函数本身进行任何更改,它现在可以在没有任何 CORS 问题的情况下运行。

我的问题不在于 CORS,而在于我的错误处理程序。 我没有拒绝承诺,而是直接在 catch 处理程序中使用throw

catch((err) => {
  throw new functions.https.HttpsError('unknown', err.message, err)
})

可能很多人会在模拟器和 cors 消息中遇到这个问题。

我在谷歌看到的任何讨论中都没有看到我的案例讨论过,我确实看到了许多“无法复制”,也许我的案例会遮住一些光:

就我而言,问题是我没有从 Firebase 模拟器运行托管。

当您通过 npm start 运行您的 React 应用程序时 - 当函数通过 firebase emulators:start 运行时,您将看到 Cors 错误。

所以在测试云函数调用时,而不是使用 npm start,你应该做 npm run build 然后从模拟器访问应用程序......

搜索类似:“托管:本地服务器: http://localhost:5000

一些注意事项 -

  • 您的功能还应该通过以下方式针对模拟器工作

    const functions = firebaseApp.functions('europe-west3');// lets assume thats your region functions.useFunctionsEmulator('http://localhost:5000');

对于在现有 GCloud 项目上启用 firebase 后遇到此错误的人来说,存在一些复杂性,如果它只是一个 firebase 应用程序,则不会自动处理。

我遇到了这个特定问题,因为我希望我的 firebase 函数可以公开访问,但是如果您使用的是谷歌的 Cloud Functions,则必须专门配置它。

以下是修复步骤:

  1. 转到云功能选项卡
  2. 选择您的云功能(复选框)
  3. 点击右侧权限选项卡下的“添加成员”
  4. 输入“所有用户”
  5. 在“新成员”下选择角色为“云函数->“云函数调用者”
  6. 节省
  7. 只需将其粘贴到浏览器中即可测试您的云功能

干杯

如果以上都没有帮助:就我而言,原因是我没有正确设置我的区域。 使用 3rd 方库时尤其会发生这种情况。

如果您使用多个环境(Firebase 项目)来分离开发和生产(即 Project-dev、Project-prod),请确保您已切换到所需的环境。 就我而言,运行它有效:

firebase use default

对我来说,我必须允许访问allUsers的所有用户。

  1. Go 到谷歌云平台控制台云功能。 您可以单击 Firebase 控制台上功能选项卡中的Detailed usage stats 在此处输入图像描述

  2. Go 到权限选项卡

  3. 点击添加

  4. 添加适当的权限在此处输入图像描述

到目前为止,我对答案的“接受”(加上我自己的个人经验)是,对于由 javascript webapp 调用的云 function,function 出现的几乎所有问题都会引发 CORS 错误。 但一个特定的错误原因是在一个区域托管 function 并从另一个区域调用它。 下面是一些代码,您可以在 Web 应用程序中使用它来明确地设置它,这样您就不会被默认值 Firebase 搞糊涂了(在任何情况下,默认值通常都不合适)。

import { initializeApp } from 'firebase/app';
import { getFunctions, httpsCallable } from 'firebase/functions';

const app = initializeApp(firebaseConfig);

const functions = getFunctions(app, '_my-region_');
const _my_function-name_= httpsCallable(functions, '_my-function-name_');

然后像这样启动 function 本身

_my-function-name_().then(response => console.log(response))

my-function-name必须返回 promise,例如:

exports.helloNewWorld = functions.region('europe-west2').https.onCall((data, context) => {
    const myPromise = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("foo");
        }, 300);
    });
    return myPromise
});

Google 关于所有这些的背景文档位于https://firebase.google.com/docs/functions/callable#web-version-9https://firebase.google.com/docs/reference/js/functions#getfunctions

我之前将我的函数部署为 HTTP 函数 ( https.onRequest ),然后切换到可调用函数 ( https.onCall )。 Firebase 无法识别此更改。

我通过删除该功能并在没有它的情况下部署,然后将该功能放回并再次部署来解决该问题。

传递给HttpsError的状态代码不能是test/code 它必须是此处列出的标准代码之一: https//firebase.google.com/docs/reference/functions/functions.https.HttpsError

  1. 错误应该在https://firebase.google.com/docs/reference/functions/functions.https.HttpsError 中给出
  2. 我在更改函数名称后部署了可调用函数并且它正在工作。

当我尝试创建用于登录 firebase 用户的自定义令牌时,我遇到了同样的错误。 我在下面附上了我的代码。 但是,我后来发现问题是由于尝试使用相同的参数多次调用该函数来创建多个令牌。

export const getCustomToken = functions.https.onCall((params: any) => {
 return admin.auth().createCustomToken(params).then((token) => {
   return token;
  }).catch((error) => {
    console.log(error);
    return null;
  });
 });

解决方案
我通过在尝试登录之前首先检查用户是否已注销来解决该问题。因此,我建议您首先检查您尝试创建的用户是否已经存在。 我知道这有点晚了,但我希望这对其他人有所帮助。

this.fireAuth.currentUser.then((signedInAlready) => {
  if (signedInAlready) {
    return this.fireAuth.signOut().then(() => getCustomToken());
  } else {
    return getCustomToken();
  }
});

在您的 firebase 函数中,您可以按如下方式检查现有用户:

admin.auth().getUserByEmail('your-email').then((userExists) => {
if (userExists) {
  // return user
} else {
  // create a new user
}});

我遇到过同样的问题。 我的解决方案是在https://console.cloud.google.com 中打开我的 Firebase 项目并导航到云功能页面。

查找您的函数名称,转到其权限页面,并将新角色“Cloud Functions Invoker”添加到“allUsers”成员。

基本上,我做了所有关于 onCall 云函数的 CORS 错误的页面和答案中提到的所有内容,从更改区域或手动添加调用权限到更明显的权限,对我来说没有任何作用。 刚刚将 onCall 转到 OnRequest 并且它起作用了。

就我而言,它只是通过 httpsCallable 传递的“未定义”值...由于该死的 CORS 错误消息,我损失了 3 个小时...这与 CORS 完全无关,我知道这是我的错未定义的变量。 但我记得现在我在 2 或 3 年前遇到了同样的问题,请谷歌,修复这个错误的错误信息!

在我的情况下,function 级别的权限也会出现问题。 我所有的可调用函数都运行良好,但只有一个。 查看他们在 GCP 中的权限,工作人员有一个“allUsers”主体,并设置了一个“Cloud Functions Invoker”角色,但不是罪魁祸首。 更新了,现在一切正常。

对于使用 gen2 firebase 函数的任何人,需要以不同方式初始化可调用函数。

在 Cloud Functions(第 2 代)支持 cloudfunctions.net URL 之前,您必须在客户端代码中使用不同的初始化程序。 与其提供 function 名称,不如向客户端 SDK 提供完整的 URL。在成功的 firebase 部署命令结束时打印 function 的 URL:

https://firebase.google.com/docs/functions/beta/callable

在 web sdk 9.12 中使用 v2 云函数时,我刚刚遇到错误。

我的解决方案是不使用 function 名称,而是使用 v2 可调用云 function 的完整名称url。

import { getFunctions, httpsCallableFromURL } from 'firebase/functions';

const functions = getFunctions();
const addMessage = httpsCallableFromURL(
  functions,
  // the URL of the function
  "https://addmessage-xyz1234-uc.a.run.app/addMessage"
);

addMessage({ text: messageText })
  .then((result) => {
    // Read result of the Cloud Function.
    const data = result.data;
    const sanitizedMessage = data.text;
  });

摘自文档的片段: https://firebase.google.com/docs/functions/beta/callable#web-version-9_2

对我有用的是删除云函数中的区域参数,然后重新部署。

functions.region("europe-west2").https.onCall(async (data) => {..

functions.https.onCall(async (data) => {..

我尝试了每一件事——没有任何效果。

  1. 删除所有 function - 不起作用...
  2. 设置 cors header - 你不能在可调用的 function 中做到这一点
  3. 添加“Cloud Functions Invoker”权限 - 它已全部设置..
  4. 添加 try catch -didnt 帮助

直到我发现有人说要更改 angular.json 中的重写规则

如何通过上下文解决 Firestore onCall function 上的 CORS

关于可调用函数中 CORs 问题的另一个文档

我的库版本

angualr 13

"@angular/fire": "^7.2.0",

"firebase": "^9.4.0",

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM