【问题标题】:Google GCM server returns Unauthorized Error 401Google GCM 服务器返回未经授权的错误 401
【发布时间】:2012-09-19 03:26:19
【问题描述】:

我正在使用 GCM 服务从服务器推送信息。如果我使用浏览器密钥,它会将成功消息显示为: {"multicast_id":4849013215736515938,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id": "0:1348742583011905%2adac3a0f9fd7ecd"}]} 但我没有在设备上收到任何通知。 如果我使用服务器密钥,它会显示 Unauthorized Error 401。我的代码如下所示:

$apiKey = "xxxxx";
$registrationIDs = array("xxxxxxxx");
$message = "testing Process";
$url = 'https://android.googleapis.com/gcm/send';
$fields = array(
        'registration_ids'  => $registrationIDs,
        'data'              => array("message"=>$message),
        );
$headers = array( 
        'Authorization: key=' . $apiKey,
        'Content-Type: application/json'
        );
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0); 
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode($fields) );

$result = curl_exec($ch);
if(curl_errno($ch)){ echo 'Curl error: ' . curl_error($ch); }
curl_close($ch);
echo $result;

请帮我解决这个问题。提前致谢。

【问题讨论】:

  • 你能做一个google配置的小步骤列表吗?
  • 对于刚刚浏览的其他人,如果您在没有进行任何特定更改(服务器密钥)仍然相同的情况下突然开始遇到此错误,您可能需要将您的项目导入 Firebase。看我的回答here

标签: php android json google-cloud-messaging


【解决方案1】:

您是否将服务器的 IP 列入白名单?默认情况下,这对于浏览器密钥不是必需的,但对于服务器密钥是必需的。

你可以在这里查看:

https://code.google.com/apis/console/#project:[您的项目编号]:access

【讨论】:

  • 谢谢大家。由于浏览器密钥和 API 密钥,我遇到了这个问题。现在它与服务器 API 密钥配合得很好。
  • 你好 Jos。我如何将我的服务器的 IP 列入白名单。 ?我收到未经授权的 401。
  • Google 稍微更新了控制台,您将被重定向到我回答中的链接。您可以在那里看到“编辑允许的 IP”按钮。我已输入“允许任何 IP”,具体取决于我的密钥的保密性以确保安全。
【解决方案2】:

另一个答案已经建议将 IP 地址列入白名单,这似乎很明显。为我解决的问题是将我的 IPv6 地址 列入白名单。那是关键!我希望这对其他人有帮助。

【讨论】:

  • 如果您使用 curl 进行调试,并且已将您的 IPv4 地址而不是您的 IPv6 地址列入白名单,您可以将 -4 传递给 curl 以使其使用 IPv4 连接。
  • 更具体地说,添加这个 curl 选项:curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
  • 对于 IPv6,相当于 0.0.0.0/0(所有 IPv4 地址)是 ::/0,仅供参考
【解决方案3】:

我尝试了此线程中的所有内容,但仍然没有运气。

所以我检查了启用的 API(APIs and Auth -> APIs, Enabled APIs),并意识到我启用了Google Cloud Messaging for Chrome 而不是Google Cloud Messaging for Android。一旦我启用了后者,它就立即起作用了。

仔细检查您是否启用了正确的 API!

【讨论】:

  • 这是一个很好的解决方案!!!效果很好。 Create a Google Cloud Messaging for Chrome 做到了这一点。谢谢你:)
【解决方案4】:

正如许多人所写,您必须将您的服务器 IPV4 和 IPV6 列入白名单。如果您只想要 IPV4,请将其添加到您的 curl php init:

curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );

【讨论】:

    【解决方案5】:

    使用浏览器密钥使用选项创建新的浏览器密钥并在您的代码中使用此密钥。 https://code.google.com/apis/console/?pli=1#project:42053154xxxx:access

    【讨论】:

    • 这就是我的问题,我试图使用服务器密钥而不是浏览器密钥,我想这更有意义,因为 Curl 更像一个网络浏览器而不是直接套接字连接。不敢相信我浪费了多少时间,除了这个 /facepalm 之外,我什么都试了
    【解决方案6】:

    我以前放的

    $apiKey = "xxxxx"
    

    像我放入 Android 客户端应用程序的项目编号(项目 ID),但我在服务器中出错必须是来自谷歌云控制台的 appkey,(您在其中激活 适用于 Android 的谷歌云消息传递 )

        ProjectXXX -> APIs & auth -> Registered Apps -> Web App -> Server Key
     -> Api key
    

    在我的情况下,我在平台上有默认项目“服务帐户项目”:“Web”,但只有 Hosted Application section 并且没有任何关于任何 api 密钥的证据。 但是当我创建名为“我的应用程序”的新 Web Apps 时,它包含 4 个部分 OAuth 2.0 Client IDCertificateServer KeyBrowser Key 我终于找到了 api 密钥;-)

    可能只有我不知道,但我相信这个答案也可能对某些人有所帮助

    【讨论】:

    • 嘿 m1uan,由于错误的 API 密钥而发生错误,现在可以正常工作了 :)
    • 很高兴听到你的声音,我很乐意提供帮助;-)
    【解决方案7】:

    对我来说,问题是您必须启用 api。设置 API 是不够的。检查适用于 Android 的 Google Cloud Messaging 是否出现在 APIs-> enabled APIs 中的已启用 APIs 上。

    如果没有单击 APIS 中的 API 库选项卡并启用它。 \

    【讨论】:

      【解决方案8】:

      如果我没记错的话,您的 APIKEY 需要进行 base64 编码。

      也可以试试 var_dump($results) 看看你能不能得到信息。

      【讨论】:

      • 嘿,伊斯卡里奥特人,base64 编码后它不会验证它。并且 var_dump($results) 在这两种情况下都显示 NULL
      • POSTS 应该是 count($fields)
      • 我对 GCM 一无所知,但我正在构建一个完整的 googlecheckout 界面,而且大部分情况下 google 就是 google 就是 google。
      • 您是否尝试将 API 密钥从浏览器 API 密钥更改为服务器 API 密钥?
      【解决方案9】:

      查看代码,我知道这是来自在线某处发布的 php-gcm 示例。它非常好,我可以向您保证,浏览器密钥和列入白名单的 ip(不是 IPV6 或 bas64 apikey)都可以工作。

      没有显示消息是因为你使用的发送通知功能'data' => array("message"=>$message) 以“消息”键为目标,这是您必须传递给未决意图的内容,即

      notification.setLatestEventInfo(context, title, message, intent);
      

      这将使意图读取包含在此键下的消息。消息本身是从下面粘贴的 GCMIntentService 方法中获取的:

       @Override
      protected void onMessage(Context context, Intent intent) {
          Log.i(TAG, "Received message");
          String message = intent.getExtras().getString("message");
          Log.d(TAG, "The intent contains: " + intent.getExtras());
          displayMessage(context, message);
          // notifies user
          generateNotification(context, message);
      }
      

      【讨论】:

        【解决方案10】:

        问题是:我使用了 2 台服务器,1 台暂存服务器,另一台用于生产服务器。对于使用数字海洋托管的登台服务器,我在服务器应用程序密钥允许的 IP 地址中输入了 inet 地址,它工作得很好。

        但是,当我从生产服务器更改为我的 inet 地址时,它失败了。相反,我不得不使用 inet6 addr: /64 Scope:Global 才能正常工作。如果遇到同样的问题,要获取该值,只需输入 ifconfig,然后找到上面的条目。在允许的 IP 地址中输入该值,它将正常工作。

        【讨论】:

          【解决方案11】:

          您必须拥有与默认项目不同的项目。创建一个项目,然后创建一个密钥。不要使用默认项目。

          【讨论】:

            【解决方案12】:

            遇到这个问题,我使用的是 GCM(Google 云消息传递)。但在 2016 年 9 月之后,GCM 上的服务器密钥将无法使用,您必须使用 FCM(firebase 云消息传递)。仅在 Firebase 控制台中使用“设置”面板的“云消息”选项卡创建新的服务器密钥。我去了firebase控制台console.firebase.google.com(我还没有使用它),它要求我导入我的项目。 GCM 控制台上突然出现了这个新的服务器密钥。如果使用 GCM,请使用您在此处看到的“旧密钥”。

            【讨论】:

              【解决方案13】:
              【解决方案14】:

              我们正在寻找解决方案。更具体地说,添加这个 curl 选项:curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2012-04-29
                • 2015-10-14
                • 2012-02-23
                • 2016-01-17
                相关资源
                最近更新 更多