You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Google Cloud Function中使用FCM?权限认证问题待解

解决Google Cloud Function中使用FCM的认证与权限问题

核心问题分析

你遇到的cloudmessaging.messages.create权限拒绝错误,本质是Cloud Function(CF)使用的服务账号缺少FCM消息发送的必要权限;同时CF环境无法直接读取本地JSON密钥文件,需要调整密钥的加载方式。


一、权限配置的正确步骤

  1. 确定CF使用的服务账号
    • 默认情况下,CF使用的服务账号格式为:[你的CF项目ID]@appspot.gserviceaccount.com;如果自定义了服务账号,以CF配置页显示的为准。
  2. 给服务账号添加FCM权限
    • 进入Firebase关联的GCP项目IAM页面,添加上述服务账号为成员,赋予Firebase Cloud Messaging Admin角色(roles/firebase.messagingAdmin)。这个角色包含cloudmessaging.messages.create权限,能直接解决权限拒绝问题。
    • 注意:如果CF和Firebase分属不同GCP项目,必须在Firebase所在项目的IAM中添加CF的服务账号,而非CF项目的IAM。

二、密钥文件的处理与代码适配

CF环境不支持读取本地文件(如WEB-INF下的JSON密钥),推荐两种方案:

方案1:使用CF默认服务账号(推荐,无需密钥文件)

GCP会自动为CF注入默认服务账号的凭证,无需手动加载JSON密钥,代码可简化为:

import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.messaging.FirebaseMessaging;

// 初始化Firebase(仅需执行一次)
if (FirebaseApp.getApps().isEmpty()) {
    FirebaseOptions options = new FirebaseOptions.Builder()
        .setCredentials(GoogleCredentials.getApplicationDefault())
        .setDatabaseUrl("https://my-firebase-project.firebaseio.com") // 无需数据库可移除
        .build();
    FirebaseApp.initializeApp(options);
}

// 发送FCM消息示例
FirebaseMessaging messaging = FirebaseMessaging.getInstance();
// 构造并发送消息(此处省略消息构造逻辑)

方案2:通过Secret Manager管理密钥文件(若必须使用自定义密钥)

  1. 存储密钥到Secret Manager
    • 在GCP控制台的Secret Manager中创建新Secret,将Firebase JSON密钥的内容粘贴进去。
    • 给CF的服务账号添加Secret Manager Secret Accessor角色(roles/secretmanager.secretAccessor),允许其读取该Secret。
  2. 代码中读取密钥并初始化
import com.google.cloud.secretmanager.v1.AccessSecretVersionResponse;
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
import com.google.cloud.secretmanager.v1.SecretVersionName;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import java.io.ByteArrayInputStream;

// 读取Secret Manager中的密钥内容
String secretId = "你的Secret名称";
String projectId = "你的CF项目ID";
try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) {
    SecretVersionName versionName = SecretVersionName.of(projectId, secretId, "latest");
    AccessSecretVersionResponse response = client.accessSecretVersion(versionName);
    String secretContent = response.getPayload().getData().toStringUtf8();

    // 初始化Firebase
    if (FirebaseApp.getApps().isEmpty()) {
        FirebaseOptions options = new FirebaseOptions.Builder()
            .setCredentials(GoogleCredentials.fromStream(
                new ByteArrayInputStream(secretContent.getBytes())
            ))
            .setDatabaseUrl("https://my-firebase-project.firebaseio.com")
            .build();
        FirebaseApp.initializeApp(options);
    }
} catch (Exception e) {
    // 处理异常
}

三、额外检查项

  • 确保Firebase项目的Firebase Cloud Messaging API已在GCP API库中启用。
  • 验证错误日志中的项目ID与代码中setDatabaseUrl或FCM调用使用的项目ID完全一致。
  • 若为跨项目调用,确认Firebase项目的IAM中已正确添加CF服务账号,且角色生效(权限变更可能需要数分钟同步)。

内容的提问来源于stack exchange,提问作者Mike Dee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 12:17:05