Firebase 401 未经授权的错误 FCM

问题描述 投票:0回答:10

我正在尝试测试 Firebase Cloud 消息 API,因为控制台无法提供所有功能(特别是应用程序在后台时的通知自定义)。但由于某些原因,我无法让它工作,并且总是显示 401 错误。我调查了原因,并在重新生成新的服务器密钥后进行了尝试,但错误仍然存在。令人惊讶的是,当我生成新的服务器密钥时,它没有反映在 Firebase 控制台中,并且将服务器密钥显示为空。另外,我尝试将我的 IP 地址添加到服务器白名单 IP,但仍然没有成功。我附上了我使用 Postman 执行的请求的屏幕截图(我用服务器密钥代替了 serverKey

我在这个问题上坚持了几个小时,非常感谢一些帮助。

android firebase-cloud-messaging
10个回答
251
投票

我不知道是否有人使用[Web API Key]作为[YOUR_SERVER_KEY]进行POSTMAN测试并不断收到“401错误”。 [Web API 密钥] 不是 [YOUR_SERVER_KEY]。

您应该转到 Firebase 控制台并检查以下内容:

获取正确的服务器密钥。

希望有帮助。


38
投票

我从您的屏幕截图中注意到您正在使用“key:serverKey”。您可以尝试使用“key=serverKey”来代替吗?

您也不需要“POST fcm.googleapus.com/fcm/send”;这不是正确的 json,可以解释您所看到的错误。请求的 URL 已在其他地方定义,因此请将其从有效负载中删除。


21
投票

我也遇到了同样的问题。

问题是我使用的是旧服务器密钥。当我使用新版本的服务器密钥时,问题解决了。

在 Firebase 控制台中转到设置 -> 云消息

然后使用新的服务器密钥。它比旧版本密钥更长。


20
投票

转到 https://console.firebase.google.com/u/0/project/[项目名称]/settings/cloudmessaging/

您可以使用服务器密钥或旧服务器密钥


2
投票

我也面临着同样的问题...我在 php 中使用curl 进行发布,并且只有当我的 LocalHost 服务器上存储有 php 文件时它才有效。当我尝试通过免费在线托管访问文件时,它显示未经授权 401。

所以我建议如果可以的话,使用本地主机。


2
投票

通过 HTTPv1 使用 FCM 的 401(承载错误和解决方案)

如果您通过 HTTP v1 使用 FCM,那么您将必须发出两个连续的 POST 请求:


1/ 在第一次通话中,您向 发出 POST

请求
https://accounts.google.com/o/oauth2/token

(或使用 API 包)使用您的 Firebase 服务帐户密钥

https://console.firebase.google.com/u/0/project/{{firebaseProjectName}}/settings/serviceaccounts/adminsdk

获取访问令牌。如果异步,请等待响应。


2/ 然后你必须向发出另一个POST

请求
https://fcm.googleapis.com/v1/projects/{{firebaseProjectName}}/messages:send

如果您已按照 Firebase 网站上从旧版 HTTP 迁移到 HTTP v1 的步骤(非常清晰的文档)进行操作,则必须对 post 请求的内容进行一些小更改,并使用“Bearer ${accessToken.data}” ' 以获得授权。

就我而言,我没有在第一个函数中正确等待 accessToken(忘记了发出 post 请求的函数前面的“await”关键字,AndroidStudio 也没有注意到有问题)。

确保等待第一个发布请求的结果,因为它是 Future。

如果不这样做,当您发出第二个 POST 请求时,Bearer 将为 null,因为您没有等待它。


1
投票

我在服务器端代码(C#)也有同样的问题。

您基本上使用了错误的服务器密钥(或 API 密钥)作为服务端代码。

按照我发布的 stackoverflow 上的链接进行操作(有助于查找服务器密钥(或 API 密钥))

FCM(Firebase 云消息传递)使用 Asp.Net 推送通知


0
投票
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.Size;

public class PushNotificationSubmit {

    public static void main(String[] args) {
        new PushNotificationSubmit().send("sample message title", "sample message body");
    }

    final String serverKey = "AAAA_*******";
    final String fcmUrl = "https://fcm.googleapis.com/fcm/send";

    /**
     * note from google: The value should be an array of registration tokens to which to send the multicast message. The array must contain at least 1 and at most 1000 registration tokens.
     * send to specific users
     *
     * @param messageTitle
     * @param messageBody
     * @param tokenList
     */
    @Size.List({@Size(min = 1), @Size(max = 999)})
    public void send(String messageTitle, String messageBody, List<String> tokenList) {
        try {
            String payloadJson = createMessageAsJson(messageTitle, messageBody, tokenList);
            doSend(payloadJson);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * send to all users that registered in my topic
     *
     * @param messageTitle
     * @param messageBody
     */
    public void send(String messageTitle, String messageBody) {
        try {
            String payloadJson = createMessageAsJson(messageTitle, messageBody, null);
            doSend(payloadJson);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String createMessageAsJson(String messageTitle, String messageBody, List<String> tokenList) {
        JSONObject payloadObj = new JSONObject();
        try {
            JSONObject notifyObj = new JSONObject();
            notifyObj.put("title", messageTitle);
            notifyObj.put("body", messageBody);
            payloadObj.put("notification", notifyObj);

            if (tokenList != null) {
                if (tokenList != null && tokenList.size() > 0) {
                    JSONArray regId = new JSONArray();
                    for (int i = 0; i < tokenList.size(); i++) {
                        regId.put(tokenList.get(i));
                    }
                    payloadObj.put("registration_ids", regId);
                }
            } else {
                payloadObj.put("to", "/topics/all");
            }

            return payloadObj.toString();
        } catch (Exception e) {
            // TODO: add logger
            e.printStackTrace();
            throw e;
        }
    }

    private void doSend(String payloadJson) throws Exception {
        HttpClient httpclient = HttpClientBuilder.create().build();
        try {
            HttpPost httpPost = new HttpPost(fcmUrl);
            httpPost.setHeader("Content-Type", "application/json");
            httpPost.setHeader("Authorization", "key=" + serverKey);
            httpPost.setEntity(new StringEntity(payloadJson, "UTF-8"));

            HttpResponse response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();

            System.out.println("push notification status: " + response.getStatusLine());
            EntityUtils.consume(entity);
        } finally {
            httpclient.getConnectionManager().shutdown();
        }
    }
}

0
投票

在 C# HttpClient 响应中

如果服务器密钥错误,会发生无效密钥、未授权、401


-1
投票

我遇到了同样的问题,我通过以下步骤解决了它

1-在发送推送的服务器中,仅使用浏览器密钥,您可以从 Firebase 控制台或 google api 控制台获取它,如下图所示:-

Google API 控制台

Firebase控制台,点击项目-->设置

注意:Firebase 控制台 Web api 密钥和 google 控制台浏览器密钥相同,您可以使用其中任何一个

2-如果您仅按照第一步操作,您将收到未经授权的错误,要解决此问题,您需要通过添加您将发送推送的服务器 IP 地址,在 google 控制台中授权您的浏览器密钥。单击 google api 控制台中浏览器键右侧的编辑铅笔图标(第一张图片上方)

添加您的 IP 地址后单击“保存” 确保您发送推送的设备令牌不为空,我希望您的推送现在能够成功发送。

© www.soinside.com 2019 - 2024. All rights reserved.