向发送请求提供授权

从您的应用服务器或受信任环境发送到 FCM 的请求必须经过授权。FCM HTTP v1 API 使用为与您的 Firebase 项目关联的服务帐号生成的 OAuth 2.0 访问令牌(在短时间内有效)。旧版协议使用从 Firebase 控制台检索的长期有效的 API 密钥。无论使用哪种协议,您都必须将所需的凭证添加到发送给 FCM 的每个消息请求。

向 HTTP v1 发送请求提供授权

每个 Firebase 项目都有一个默认的服务帐号。您可以使用此帐号从您的应用服务器或受信任环境调用 Firebase 服务器 API。如果您要使用其他服务帐号,请确保帐号拥有修改者或所有者权限。

要对服务帐号进行身份验证并授权其访问 Firebase 服务,您必须生成 JSON 格式的私钥文件,并使用此密钥来检索在短时间内有效的 OAuth 2.0 令牌。获得有效令牌后,您可以根据各种 Firebase 服务(如远程配置或 FCM)的要求将其添加到服务器请求中。

要为您的服务帐号生成私钥文件,请执行以下操作:

  1. 在 Firebase 控制台中,打开设置 > 服务帐号
  2. 点击生成新的私钥,然后点击生成密钥进行确认。
  3. 妥善存储包含密钥的 JSON 文件。您将需要此文件才能完成下一步操作。

检索访问令牌:

要检索令牌,您可以使用与您偏好的编程语言对应的 Google API 客户端库,并按如下所示引用私钥 JSON 文件:

node.js

function getAccessToken() {
  return new Promise(function(resolve, reject) {
    var key = require('./service-account.json');
    var 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);
    });
  });
}

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

Java

private static String getAccessToken() throws IOException {
  GoogleCredential googleCredential = GoogleCredential
      .fromStream(new FileInputStream("service-account.json"))
      .createScoped(Arrays.asList(SCOPES));
  googleCredential.refreshToken();
  return googleCredential.getAccessToken();
}

在您的令牌过期后,系统会自动调用令牌刷新方法以检索更新的令牌。

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

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

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

node.js

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

Python

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

Java

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,您必须使用这个服务器密钥来建立连接。

向 HTTP 请求提供授权

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

  • Authorization: key=YOUR_SERVER_KEY
    请确保这是 server(服务器)密钥,您可以在 Firebase 控制台中进入设置窗格的云消息传递标签找到该密钥的值。Android 密钥、iOS 密钥和浏览器密钥会被 FCM 拒绝。
  • Content-Type: application/json(JSON 格式);application/x-www-form-urlencoded;charset=UTF-8(纯文本格式)。
    如果省略 Content-Type,则视为纯文本格式。

例如:

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

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

如需详细了解如何创建发送请求,请参阅构建发送请求旧版 HTTP 协议参考提供了您的消息可以包含的所有参数的列表。

检查服务器密钥的有效性

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

# 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>@gcm.googleapis.com(FCM 发送者 ID)并以服务器密钥作为密码的 SASL PLAIN 身份验证机制。您可以在 Firebase 控制台中进入设置窗格的云消息传递标签找到这些值。

无论连接在哪个时间失败,您都应立即重新连接。如果在身份验证后连接断开,您无需退避。对于每个发送者 ID,FCM 允许 1000 个并行连接。

以下这段代码说明了如何进行身份验证以及为与 FCM 的 XMPP 连接提供授权。

XMPP 服务器

XMPP 服务器请求连接到 FCM

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

FCM

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>

FCM

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

XMPP 服务器

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

FCM

<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>

FCM

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

注意:FCM 在传递消息时不使用绑定的资源。

如需详细了解如何创建发送请求,请参阅构建发送请求旧版 XMPP 协议参考提供了您的消息可以包含的所有参数的列表。

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面