网络推送通知已发送,但浏览器未显示通知

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

我一直在尝试制作自己的推送通知 API。我已经使令牌正常工作,并且端点不再有任何错误响应。该消息似乎发送到终点很好,但我在浏览器上从未收到任何内容。

我将展示我用来加密有效负载的代码和我制作的 Service Worker。

我收到 201 响应,表示已收到并接受。 以下是我用来创建此内容的资源:

https://web-push-book.gauntface.com/web-push-protocol/

https://blog.mozilla.org/services/2016/08/23/sending-vapid-identified-webpush-notifications-via-mozillas-push-service/

这是我用来加密有效负载的方法。

    $payload = [
        'notification' => [
            'title' => 'New Notification',
            'body' => 'This is the body of the notification.',
            'icon' => 'icon.png'
        ]
    ];

    $localJWK = new JWK();
    $localJWK->create();

    $userJWK = new JWK();
    [$x, $y] = $userJWK->decode_public_key($subscription->keys->p256dh);
    $userJWK->create(
        [
            'x' => $x,
            'y' => $y
        ]
    );

    $sharedSecret = openssl_pkey_derive($userJWK->public_to_pem(), $localJWK->private_to_pem(), 256);
    $sharedSecret = str_pad($sharedSecret, 32, chr(0), STR_PAD_LEFT);

    //AES-GCM-128
    $decodedLocalPublicKey = base64url_decode($localJWK->public_to_base64());

    $info = 'WebPush: info'.chr(0).base64url_decode($subscription->keys->p256dh).$decodedLocalPublicKey;
    $ikm = hkdf(base64url_decode($subscription->keys->auth), $sharedSecret, $info, 32);
    echo bin2hex($ikm).PHP_EOL;

    //$length = chr(0).'A';
    //$context = chr(0).$length.(0x04.$x.$y).$length.(0x04.$localJWK->getXandY());

    $salt = base64url_encode(random_bytes(16));
    $contentEncryptionKey = hkdf($salt, $ikm, 'Content-Encoding: aes128gcm'.chr(0), 16);
    echo bin2hex($contentEncryptionKey).PHP_EOL;

    $nonce = hkdf($salt, $ikm, 'Content-Encoding: nonce'.chr(0), 12);
    echo bin2hex($nonce).PHP_EOL.PHP_EOL;

    $tag = '';
    $encryptedPayload = openssl_encrypt(json_encode($payload), 'aes-128-gcm', $contentEncryptionKey, OPENSSL_RAW_DATA, $nonce, $tag);

    $content = $salt.pack('N*', 4096).pack('C*', mb_strlen($decodedLocalPublicKey, '8bit')).$decodedLocalPublicKey.$encryptedPayload;

    $headers = [
        'TTL: '.(60*60*12), //12-24 hours
        'Urgency: normal', //<very-low | low | normal | high>
        'Content-Type: application/octet-stream',
        'Content-Encoding: aes128gcm',
        'Content-Length: '.mb_strlen($content, '8bit'),
        'Authorization: WebPush '.$token,
        //'Encryption: salt='.base64url_encode($salt),
        //'Authorization: vapid t='.$token.',k='.$publicKey,
        //'Authorization: key=' . $subscription->keys->auth,
        'Crypto-Key: p256ecdsa='.$keys['publicKey'],//.';dh='.$localJWK->public_to_base64(),//$subscription->keys->auth,
        //'Crypto-Key: p256ecdsa='.$subscription->keys->p256dh.';dh='.$subscription->keys->auth,//$subscription->keys->p256dh,
        'Content-Type: application/json',
    ];

    $options = [
        CURLOPT_URL => $subscription->endpoint,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $content,
        CURLOPT_RETURNTRANSFER => true,
    ];

    $ch = curl_init();
    curl_setopt_array($ch, $options);
    $result = curl_exec($ch);

    if ($result === false) {
        echo 'Error: ' . curl_error($ch) . PHP_EOL;
    } else {
        echo 'Push notification sent successfully!' . PHP_EOL;
    }

    function hkdf($salt, $ikm, $info, $length){
        $prk = hash_hmac('sha256', $ikm, $salt, true);
        return mb_substr(hash_hmac('sha256', $info.chr(1), $prk, true), 0, $length, '8bit');
    }

    function base64url_encode($data){
        return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
    }

    function base64url_decode($data){
        return base64_decode(strtr($data, '-_', '+/'));
    }

为了展示 JWK 类,我将发布它的要点。 https://gist.github.com/DrBrad/882d5a932df4a441ae7763ddc3b1f174

最后这是我的服务人员:

self.addEventListener('push', function (event) {
    console.log(event);
});
javascript php browser notifications
1个回答
0
投票

事实证明问题出在我的盐、PKR 和内容填充上。

我在 GitHub 上有固定代码: https://github.com/DrBrad/PHP-Web-Push-Notifications/tree/main

此资源帮助我分配解决此问题: https://tests.peter.sh/push-encryption-verifier/

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