获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

授权发送请求

从您的应用服务器或可信环境发送到 FCM 的请求必须经过授权。请注意旧版 HTTP 和 HTTP v1 API 授权之间的这些重要区别:

  • FCM HTTP v1 API 使用短期 OAuth 2.0 访问令牌授权请求。要创建此令牌,您可以使用 Google 应用程序默认凭据(在 Google 服务器环境中)和/或从为服务帐户生成的 JSON 私钥文件中手动获取所需的凭据。如果您使用 Firebase Admin SDK 发送消息,该库会为您处理令牌。
  • 旧协议只能使用从 Firebase 控制台获取的长期 API 密钥。

授权 HTTP v1 发送请求

根据您的服务器环境的详细信息,使用这些策略的组合来授权对 Firebase 服务的服务器请求:

  • Google 应用程序默认凭据 (ADC)
  • 服务帐号 JSON 文件
  • 从服务帐户派生的短期 OAuth 2.0 访问令牌

如果您的应用在 Compute Engine、Google Kubernetes Engine、App Engine 或 Cloud Functions(包括 Cloud Functions for Firebase)上运行,请使用应用默认凭据 (ADC)。 ADC 使用您现有的默认服务帐户来获取授权请求的凭据,并且 ADC 通过环境变量GOOGLE_APPLICATION_CREDENTIALS启用灵活的本地测试。要实现授权流程的最全面自动化,请将 ADC 与 Admin SDK 服务器库一起使用。

如果您的应用在非 Google 服务器环境中运行,您需要从 Firebase 项目下载服务帐号 JSON 文件。只要您有权访问包含私钥文件的文件系统,就可以使用环境变量GOOGLE_APPLICATION_CREDENTIALS使用这些手动获取的凭据来授权请求​​。如果您缺乏此类文件访问权限,则必须在代码中引用服务帐户文件 - 由于存在暴露您的凭据的风险,因此应格外小心。

使用 ADC 提供凭据

Google 应用程序默认凭据 (ADC) 按以下顺序检查您的凭据:

  1. ADC 检查是否设置了环境变量GOOGLE_APPLICATION_CREDENTIALS 。如果设置了变量,ADC 将使用变量指向的服务帐户文件。

  2. 如果未设置环境变量,ADC 将使用 Compute Engine、Google Kubernetes Engine、App Engine 和 Cloud Functions 为在这些服务上运行的应用程序提供的默认服务帐户。

  3. 如果 ADC 无法使用上述任一凭据,系统将引发错误。

以下 Admin SDK 代码示例说明了此策略。该示例未明确指定应用程序凭据。但是,只要设置了环境变量,或者只要应用程序在 Compute Engine、Google Kubernetes Engine、App Engine 或 Cloud Functions 上运行,ADC 就能够隐式找到凭据。

节点.js

admin.initializeApp({
  credential: admin.credential.applicationDefault(),
});

爪哇

FirebaseOptions options = FirebaseOptions.builder()
    .setCredentials(GoogleCredentials.getApplicationDefault())
    .setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/")
    .build();

FirebaseApp.initializeApp(options);

Python

default_app = firebase_admin.initialize_app()

app, err := firebase.NewApp(context.Background(), nil)
if err != nil {
	log.Fatalf("error initializing app: %v\n", err)
}

C#

FirebaseApp.Create(new AppOptions()
{
    Credential = GoogleCredential.GetApplicationDefault(),
});

手动提供凭据

Firebase 项目支持 Google服务帐户,您可以使用它从您的应用服务器或受信任的环境中调用 Firebase 服务器 API。如果您在本地开发代码或在本地部署应用程序,则可以使用通过此服务帐户获得的凭据来授权服务器请求。

要对服务帐号进行身份验证并授权其访问 Firebase 服务,您必须生成 JSON 格式的私钥文件。

要为您的服务帐户生成私钥文件:

  1. 在 Firebase 控制台中,打开Settings > Service Accounts

  2. 单击Generate New Private Key ,然后单击Generate Key进行确认。

  3. 安全地存储包含密钥的 JSON 文件。

通过服务帐户进行授权时,您有两种选择来向您的应用程序提供凭据。您可以设置GOOGLE_APPLICATION_CREDENTIALS环境变量,也可以在代码中将路径显式传递给服务帐户密钥。第一个选项更安全,强烈推荐。

设置环境变量:

将环境变量GOOGLE_APPLICATION_CREDENTIALS设置为包含您的服务帐号密钥的 JSON 文件的文件路径。此变量仅适用于您当前的 shell 会话,因此如果您打开一个新会话,请再次设置该变量。

Linux 或 macOS

export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/service-account-file.json"

视窗

使用 PowerShell:

$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\service-account-file.json"

完成上述步骤后,应用程序默认凭据 (ADC) 能够隐式确定您的凭据,允许您在测试或在非 Google 环境中运行时使用服务帐户凭据。

使用凭证来铸造访问令牌

除非您使用的是自动处理授权的Admin SDK ,否则您需要生成访问令牌并将其添加到发送请求中。

将您的 Firebase 凭据与您的首选语言的Google 身份验证库一起使用,以检索短期 OAuth 2.0 访问令牌:

节点.js

 function getAccessToken() {
  return new Promise(function(resolve, reject) {
    const key = require('../placeholders/service-account.json');
    const jwtClient = new google.auth.JWT(
      key.client_email,
      null,
      key.private_key,
      SCOPES,
      null
    );
    jwtClient.authorize(function(err, tokens) {
      if (err) {
        reject(err);
        return;
      }
      resolve(tokens.access_token);
    });
  });
}

在此示例中,Google API 客户端库使用 JSON Web 令牌或 JWT 对请求进行身份验证。有关更多信息,请参阅JSON Web 令牌

Python

def _get_access_token():
  """Retrieve a valid access token that can be used to authorize requests.

  :return: Access token.
  """
  credentials = ServiceAccountCredentials.from_json_keyfile_name(
      'service-account.json', SCOPES)
  access_token_info = credentials.get_access_token()
  return access_token_info.access_token

爪哇

private static String getAccessToken() throws IOException {
  GoogleCredentials googleCredentials = GoogleCredentials
          .fromStream(new FileInputStream("service-account.json"))
          .createScoped(Arrays.asList(SCOPES));
  googleCredentials.refreshAccessToken();
  return googleCredentials.getAccessToken().getTokenValue();
}

访问令牌过期后,会自动调用令牌刷新方法来检索更新的访问令牌。

要授权访问 FCM,请请求范围https://www.googleapis.com/auth/firebase.messaging

要将访问令牌添加到 HTTP 请求标头:

将令牌添加为Authorization标头的值,格式为Authorization: Bearer <access_token>

节点.js

headers: {
  'Authorization': 'Bearer ' + accessToken
}

Python

headers = {
  'Authorization': 'Bearer ' + _get_access_token(),
  'Content-Type': 'application/json; UTF-8',
}

爪哇

URL url = new URL(BASE_URL + FCM_SEND_ENDPOINT);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestProperty("Authorization", "Bearer " + getAccessToken());
httpURLConnection.setRequestProperty("Content-Type", "application/json; UTF-8");
return httpURLConnection;

授权遗留协议发送请求

使用 HTTP 旧协议,每个请求都必须包含 Firebase 控制台设置窗格的云消息传递选项卡中的服务器密钥。对于 XMPP,您必须使用相同的服务器密钥来建立连接。

迁移旧服务器密钥

从 2020 年 3 月开始,FCM 停止创建旧版服务器密钥。现有的旧服务器密钥将继续有效,但我们建议您改用Firebase 控制台中标有服务器密钥的更新版本的密钥。

如果您想删除现有的旧服务器密钥,可以在Google Cloud Console中执行此操作。

授权 HTTP 请求

消息请求由两部分组成:HTTP 标头和 HTTP 正文。 HTTP 标头必须包含以下标头:

  • Authorization :key=YOUR_SERVER_KEY
    确保这是服务器密钥,其值在 Firebase 控制台设置窗格的云消息传递选项卡中可用。 FCM 拒绝 Android、Apple 平台和浏览器密钥。
  • Content-Type : JSON 的application/jsonapplication/x-www-form-urlencoded;charset=UTF-8用于纯文本。
    如果省略Content-Type ,则假定格式为纯文本。

例如:

Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{
  "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
  "data" : {
    ...
  },
}

有关创建发送请求的完整详细信息,请参阅构建发送请求。 Legacy HTTP 协议参考提供了您的消息可以包含的所有参数的列表。

检查服务器密钥的有效性

如果您在发送消息时收到身份验证错误,请检查您的服务器密钥的有效性。例如,在 Linux 上,运行以下命令:

api_key=YOUR_SERVER_KEY

curl --header "Authorization: key=$api_key" \
     --header Content-Type:"application/json" \
     https://fcm.googleapis.com/fcm/send \
     -d "{\"registration_ids\":[\"ABC\"]}"

如果您收到 401 HTTP 状态代码,则您的服务器密钥无效。

授权 XMPP 连接

使用 XMPP,您可以保持与 FCM 服务器的持久、异步、双向连接。该连接可用于在您的服务器和用户的 FCM 连接设备之间发送和接收消息。

您可以使用大多数 XMPP 库来管理与 FCM 的长期连接。 XMPP 端点在fcm-xmpp.googleapis.com:5235运行。在使用非生产用户测试功能时,您应该连接到位于fcm-xmpp.googleapis.com:5236的预生产服务器(注意不同的端口)。

对预生产(运行最新 FCM 构建的较小环境)进行定期测试有助于将真实用户与测试代码隔离开来。连接到fcm-xmpp.googleapis.com:5236的测试设备和测试代码应使用不同的 FCM 发件人 ID,以避免向生产用户发送测试消息或通过测试连接从生产流量发送上游消息的任何风险。

连接有两个重要要求:

  • 您必须启动传输层安全 (TLS) 连接。请注意,FCM 目前不支持STARTTLS 扩展
  • FCM 需要使用<your_FCM_Sender_Id>@fcm.googleapis.com (FCM发件人 ID )和服务器密钥作为密码的 SASL PLAIN 身份验证机制。这些值在 Firebase 控制台设置窗格的云消息传递选项卡中可用。

如果在任何时候连接失败,您应该立即重新连接。在身份验证后发生断开连接后,无需退出。对于每个发件人 ID ,FCM 允许并行连接 2500 个。

以下代码片段说明了如何为与 FCM 的 XMPP 连接执行身份验证和授权。

XMPP 服务器

XMPP 服务器请求与 FCM 的连接

<stream:stream to="fcm.googleapis.com"
        version="1.0" xmlns="jabber:client"
        xmlns:stream="http://etherx.jabber.org/streams">

流式细胞仪

FCM 打开连接并请求认证机制,包括PLAIN方法。

<stream:features>
  <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
    <mechanism>X-OAUTH2</mechanism>
    <mechanism>X-GOOGLE-TOKEN</mechanism>
    <mechanism>PLAIN</mechanism>
  </mechanisms>
</stream:features>

XMPP 服务器

XMPP 服务器必须使用PLAIN身份验证方法进行响应,从 Firebase 控制台设置窗格的云消息传递选项卡提供服务器密钥。

<auth mechanism="PLAIN"
xmlns="urn:ietf:params:xml:ns:xmpp-sasl">MTI2MjAwMzQ3OTMzQHByb2plY3RzLmdjbS5hb
mFTeUIzcmNaTmtmbnFLZEZiOW1oekNCaVlwT1JEQTJKV1d0dw==</auth>

流式细胞仪

<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>

XMPP 服务器

<stream:stream to="fcm.googleapis.com"
        version="1.0" xmlns="jabber:client"
        xmlns:stream="http://etherx.jabber.org/streams">

流式细胞仪

<stream:features>
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
  <session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>
</stream:features>

XMPP 服务器

<iq type="set">
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"></bind>
</iq>

流式细胞仪

<iq type="result">
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
    <jid>SENDER_ID@fcm.googleapis.com/RESOURCE</jid>
  </bind>
</iq>

注意:FCM 在路由消息时不使用绑定资源。

有关创建发送请求的完整详细信息,请参阅构建发送请求。 Legacy XMPP 协议参考提供了您的消息可以包含的所有参数的列表。