从您的应用服务器或可信环境发送到 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) 按以下顺序检查您的凭据:
ADC 检查是否设置了环境变量GOOGLE_APPLICATION_CREDENTIALS 。如果设置了该变量,ADC 将使用该变量指向的服务帐户文件。
如果未设置环境变量,ADC 将使用 Compute Engine、Google Kubernetes Engine、App Engine 和 Cloud Functions 为在这些服务上运行的应用程序提供的默认服务帐户。
如果 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 格式的私钥文件。
为您的服务帐户生成私钥文件:
在 Firebase 控制台中,打开设置 >服务帐户。
点击Generate New Private Key ,然后点击Generate Key确认。
安全地存储包含密钥的 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 Auth 库一起使用,以检索短期 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 网络令牌或 JWT 对请求进行身份验证。有关详细信息,请参阅JSON Web 令牌。
Python
def _get_access_token():
"""Retrieve a valid access token that can be used to authorize requests.
:return: Access token.
"""
credentials = service_account.Credentials.from_service_account_file(
'service-account.json', scopes=SCOPES)
request = google.auth.transport.requests.Request()
credentials.refresh(request)
return credentials.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: Bearer <access_token>
格式添加令牌作为Authorization
标头的值:
节点.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 控制台中标记为Server key的更新版本的密钥。
如果您想删除现有的遗留服务器密钥,您可以在Google Cloud Console中执行此操作。
授权 HTTP 请求
消息请求由两部分组成:HTTP 标头和 HTTP 正文。 HTTP 标头必须包含以下标头:
-
Authorization
:key=YOUR_SERVER_KEY
确保这是服务器密钥,其值在 Firebase 控制台设置窗格的云消息传递选项卡中可用。 Android、Apple 平台和浏览器密钥被 FCM 拒绝。 -
Content-Type
:JSON 的application/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" : { ... }, }
有关创建发送请求的完整详细信息,请参阅构建发送请求。 Legacy HTTP Protocol Reference提供了您的消息可以包含的所有参数的列表。
检查服务器密钥的有效性
如果您在发送消息时收到身份验证错误,请检查您的服务器密钥的有效性。例如,在 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
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="fcm.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@fcm.googleapis.com/RESOURCE</jid> </bind> </iq>
注意:FCM 在路由消息时不使用绑定资源。
有关创建发送请求的完整详细信息,请参阅构建发送请求。 Legacy XMPP Protocol Reference提供了您的消息可以包含的所有参数的列表。