Azure 通知中心 - 401 MissingToken:未找到授权标头

Posted

技术标签:

【中文标题】Azure 通知中心 - 401 MissingToken:未找到授权标头【英文标题】:Azure Notification Hub - 401 MissingToken: The authorization header was not found 【发布时间】:2017-02-23 18:38:29 【问题描述】:

我遇到了一点问题,我正在尝试让 php 工作的 Notification Hub REST 包装器。我按照说明插入了正确的凭据,但仍然收到错误消息:

“致命错误:未捕获的异常 'Exception' 带有消息 'Error 发送通知:401 消息: 401MissingToken:授权头 不是 找到..TrackingId:7392381b-7e4b-4ced-9090-6f3f8beac79d_G19,时间戳:2/23/2017 下午 5:44:36' 在 /"PATH"/class.NotificationHub.php:127 堆栈跟踪:#0 /"PATH"/testingOfNotification.php(21): NotificationHub->sendNotification(Object(Notification), NULL) #1 main 在第 127 行的 /"PATH"/class.NotificationHub.php 中抛出"

我遵循的指南是this guide。

这是我的代码:

require_once("class.NotificationHub.php");

    $hub = new NotificationHub("Endpoint=sb://XXXX.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=XXXX", "XXXX");

$message = '"data":"message":"Hello from PHP!"';

$notification = new Notification("gcm", $message);

$hub->sendNotification($notification, null);

class.Notification.php

class Notification 
    public $format;
    public $payload;
    public $headers;

    function __construct($format, $payload) 
        if (!in_array($format, ["template", "apple", "windows", "gcm", "windowsphone"])) 
            throw new Exception('Invalid format: ' . $format);
        
        $this->format = $format;
        $this->payload = $payload;
    

class.NotificationHub

include 'class.Notification.php';

class NotificationHub 

const API_VERSION = "?api-version=2013-10";
private $endpoint;
private $hubPath;
private $sasKeyName;
private $sasKeyValue;

function __construct($connectionString, $hubPath) 

    $this->hubPath = $hubPath;
    $this->parseConnectionString($connectionString);


private function parseConnectionString($connectionString) 

    $parts = explode(";", $connectionString);

    if (sizeof($parts) != 3) 
        throw new Exception("Error parsing connection string: " . $connectionString);
    

    foreach ($parts as $part) 
        if (strpos($part, "Endpoint") === 0) 
            $this->endpoint = "https" . substr($part, 11);
         else if (strpos($part, "SharedAccessKeyName") === 0) 
            $this->sasKeyName = substr($part, 20);
         else if (strpos($part, "SharedAccessKey") === 0) 
            $this->sasKeyValue = substr($part, 16);
        
    


public function generateSasToken($uri) 

    $targetUri = strtolower(rawurlencode(strtolower($uri)));
    $expires = time();
    $expiresInMins = 60;
    $expires = $expires + $expiresInMins * 60;
    $toSign = $targetUri . "\n" . $expires;
    $signature = rawurlencode(base64_encode(hash_hmac('sha256', $toSign, $this->sasKeyValue, TRUE)));
    $token = "SharedAccessSignature sr=" . $targetUri . "&sig="
        . $signature . "&se=" . $expires . "&skn=" . $this->sasKeyName;

    return $token;


public function broadcastNotification($notification) 
    $this->sendNotification($notification, "");


public function sendNotification($notification, $tagsOrTagExpression) 

    echo $tagsOrTagExpression."<p>";

    if (is_array($tagsOrTagExpression)) 
        $tagExpression = implode(" || ", $tagsOrTagExpression);
     else 
        $tagExpression = $tagsOrTagExpression;
    

    # build uri
    $uri = $this->endpoint . $this->hubPath . "/messages" . NotificationHub::API_VERSION;
    echo $uri."<p>";

    $ch = curl_init($uri);

    if (in_array($notification->format, ["template", "apple", "gcm"])) 
        $contentType = "application/json"; //;charset=utf-8
     else 
        $contentType = "application/xml";
    
    $token = $this->generateSasToken($uri);

    //printArr($token, "token"); die();

    $headers = [
        'Authorization: '.$token,
        'Content-Type: '.$contentType,
        'ServiceBusNotification-Format: '.$notification->format
    ];

    printArr($headers);

    if ("" !== $tagExpression) 
        $headers[] = 'ServiceBusNotification-Tags: '.$tagExpression;
    

    # add headers for other platforms
    if (is_array($notification->headers)) 
        $headers = array_merge($headers, $notification->headers);
    

    curl_setopt_array($ch, array(
        //CURLOPT_CUSTOMREQUEST => 'PUT',
        CURLOPT_POST => TRUE,
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_SSL_VERIFYPEER => FALSE,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_POSTFIELDS => $notification->payload
    ));
    // Send the request
    $response = curl_exec($ch);

    // Check for errors
    if($response === FALSE)
        throw new Exception(curl_error($ch));
    

    $info = curl_getinfo($ch);
    if ($info['http_code'] <> 201) 
        throw new Exception('Error sending notificaiton: '. $info['http_code'] . ' msg: ' . $response);
    
    //print_r($info);
    //echo $response;


所以我的问题是我错了吗?我知道从 Azure 通知中心到我的 android 应用程序的连接正常,因为从 Azure 发送的测试通知将显示在我的设备上。

【问题讨论】:

【参考方案1】:

错误提示:The authorization header was not found。但是标头已经在您的代码中传递。因此,请仔细检查您发布的代码是否与您服务器上运行的代码完全相同。

我还在我的网站上对其进行了测试,效果很好。

这是我的截图:

【讨论】:

感谢您的回复 :) 昨天在我发布问题之前,我在 Azure 中创建了一个新的命名空间和通知中心,我尝试了一下,但得到了相同的结果。但现在它以某种方式起作用,我真的不知道为什么。但是非常感谢您抽出宝贵的时间。 -克里斯蒂安

以上是关于Azure 通知中心 - 401 MissingToken:未找到授权标头的主要内容,如果未能解决你的问题,请参考以下文章

通过新门户中的 Azure 通知中心发送通知

Azure 通知中心延迟问题

如何使用 Azure 通知中心?

Azure 通知中心的 Xamarin.Forms PushNotifications

Azure 通知中心不会发送苹果推送通知

Azure 通知中心 [关闭]