Wir haben gesehen, wie eine Bibliothek zum Auslösen von Push-Benachrichtigungen verwendet werden kann. Aber was genau machen diese Bibliotheken?
Sie stellen Netzwerkanfragen und sorgen dafür, dass diese das richtige Format haben. Die Spezifikation, die diese Netzwerkanfrage definiert, ist das Web-Push-Protokoll.
In diesem Abschnitt wird beschrieben, wie sich der Server mit Anwendungsserverschlüsseln identifizieren kann und wie die verschlüsselte Nutzlast und die zugehörigen Daten gesendet werden.
Das ist keine schöne Seite von Web-Push und ich bin kein Experte für Verschlüsselung, aber sehen wir uns die einzelnen Teile an, da es nützlich ist, zu wissen, was diese Bibliotheken im Hintergrund tun.
Anwendungsserverschlüssel
Wenn wir einen Nutzer abonnieren, übergeben wir eine applicationServerKey. Dieser Schlüssel wird an den Push-Dienst übergeben und verwendet, um zu prüfen, ob die Anwendung, die den Nutzer abonniert hat, auch die Anwendung ist, die Push-Nachrichten auslöst.
Wenn wir eine Push-Nachricht auslösen, senden wir eine Reihe von Headern, mit denen der Push-Dienst die Anwendung authentifizieren kann. (Dies wird durch die VAPID-Spezifikation definiert.)
Was bedeutet das alles und was genau passiert? Dies sind die Schritte für die Authentifizierung des Anwendungsservers:
- Der Anwendungsserver signiert einige JSON-Informationen mit seinem privaten Anwendungsschlüssel.
- Diese signierten Informationen werden als Header in einer POST-Anfrage an den Push-Dienst gesendet.
- Der Push-Dienst verwendet den gespeicherten öffentlichen Schlüssel, den er von
pushManager.subscribe()erhalten hat, um zu prüfen, ob die empfangenen Informationen mit dem privaten Schlüssel signiert sind, der zum öffentlichen Schlüssel gehört. Hinweis: Der öffentliche Schlüssel ist derapplicationServerKey, der im Subscribe-Aufruf übergeben wird. - Wenn die signierten Informationen gültig sind, sendet der Push-Dienst die Push-Benachrichtigung an den Nutzer.
Hier ein Beispiel für diesen Informationsfluss: (Beachten Sie die Legende unten links, die öffentliche und private Schlüssel kennzeichnet.)
Die „signierten Informationen“, die einem Header in der Anfrage hinzugefügt werden, sind ein JSON Web Token.
JSON-Webtoken
Ein JSON-Webtoken (kurz JWT) ist eine Möglichkeit, eine Nachricht an einen Drittanbieter zu senden, sodass der Empfänger prüfen kann, wer sie gesendet hat.
Wenn ein Drittanbieter eine Nachricht erhält, muss er den öffentlichen Schlüssel des Absenders abrufen und damit die Signatur des JWT validieren. Wenn die Signatur gültig ist, muss das JWT mit dem übereinstimmenden privaten Schlüssel signiert worden sein und stammt daher vom erwarteten Absender.
Auf jwt.io/ gibt es eine Reihe von Bibliotheken, die die Signierung für Sie übernehmen können. Ich empfehle Ihnen, diese nach Möglichkeit zu verwenden. Der Vollständigkeit halber sehen wir uns an, wie Sie ein signiertes JWT manuell erstellen.
Web-Push und signierte JWTs
Ein signiertes JWT ist nur ein String, kann aber als drei durch Punkte verbundene Strings betrachtet werden.
Der erste und der zweite String (die JWT-Informationen und die JWT-Daten) sind JSON-Teile, die base64-codiert wurden, d. h., sie sind öffentlich lesbar.
Der erste String enthält Informationen zum JWT selbst und gibt an, welcher Algorithmus zum Erstellen der Signatur verwendet wurde.
Die JWT-Informationen für Web-Push-Benachrichtigungen müssen die folgenden Informationen enthalten:
{
"typ": "JWT",
"alg": "ES256"
}
Der zweite String sind die JWT-Daten. Diese enthält Informationen zum Absender des JWT, zum Empfänger und zur Gültigkeitsdauer.
Bei Web-Push-Benachrichtigungen haben die Daten folgendes Format:
{
"aud": "https://some-push-service.org",
"exp": "1469618703",
"sub": "mailto:example@web-push-book.org"
}
Der Wert aud ist die „Zielgruppe“, d.h. für wen das JWT bestimmt ist. Bei Web-Push ist die Zielgruppe der Push-Dienst. Daher legen wir sie auf den Ursprung des Push-Dienstes fest.
Der Wert exp ist der Ablauf des JWT. Dadurch wird verhindert, dass Schnüffler ein JWT wiederverwenden können, wenn sie es abfangen. Der Ablauf ist ein Zeitstempel in Sekunden und darf nicht länger als 24 Stunden sein.
In Node.js wird der Ablauf so festgelegt:
Math.floor(Date.now() / 1000) + 12 * 60 * 60;
Es sind 12 Stunden statt 24 Stunden, um Probleme mit Zeitunterschieden zwischen der sendenden Anwendung und dem Push-Dienst zu vermeiden.
Der Wert für sub muss entweder eine URL oder eine mailto-E-Mail-Adresse sein.
So kann ein Push-Dienst, der den Absender kontaktieren muss, die Kontaktdaten aus dem JWT abrufen. (Deshalb benötigte die Web-Push-Bibliothek eine E-Mail-Adresse.)
Genau wie die JWT-Informationen werden die JWT-Daten als URL-sicherer Base64-String codiert.
Der dritte String, die Signatur, ist das Ergebnis der ersten beiden Strings (JWT-Informationen und JWT-Daten), die mit einem Punktzeichen verbunden werden, das wir als „nicht signiertes Token“ bezeichnen, und signiert werden.
Beim Signieren muss das „unsignierte Token“ mit ES256 verschlüsselt werden. Gemäß der JWT-Spezifikation ist ES256 die Abkürzung für „ECDSA mit der P-256-Kurve und dem SHA-256-Hash-Algorithmus“. Mit Web Crypto können Sie die Signatur so erstellen:
// Utility function for UTF-8 encoding a string to an ArrayBuffer.
const utf8Encoder = new TextEncoder('utf-8');
// The unsigned token is the concatenation of the URL-safe base64 encoded
// header and body.
const unsignedToken = .....;
// Sign the |unsignedToken| using ES256 (SHA-256 over ECDSA).
const key = {
kty: 'EC',
crv: 'P-256',
x: window.uint8ArrayToBase64Url(
applicationServerKeys.publicKey.subarray(1, 33)),
y: window.uint8ArrayToBase64Url(
applicationServerKeys.publicKey.subarray(33, 65)),
d: window.uint8ArrayToBase64Url(applicationServerKeys.privateKey),
};
// Sign the |unsignedToken| with the server's private key to generate
// the signature.
return crypto.subtle.importKey('jwk', key, {
name: 'ECDSA', namedCurve: 'P-256',
}, true, ['sign'])
.then((key) => {
return crypto.subtle.sign({
name: 'ECDSA',
hash: {
name: 'SHA-256',
},
}, key, utf8Encoder.encode(unsignedToken));
})
.then((signature) => {
console.log('Signature: ', signature);
});
Ein Push-Dienst kann ein JWT mit dem öffentlichen Anwendungsserverschlüssel validieren, um die Signatur zu entschlüsseln und sicherzustellen, dass der entschlüsselte String mit dem „unsignierten Token“ (d.h. den ersten beiden Strings im JWT) übereinstimmt.
Das signierte JWT (d.h. alle drei Strings, die durch Punkte verbunden sind) wird als Authorization-Header mit vorangestelltem WebPush an den Web-Push-Dienst gesendet, etwa so:
Authorization: 'WebPush [JWT Info].[JWT Data].[Signature]';
Im Web-Push-Protokoll ist außerdem festgelegt, dass der öffentliche Anwendungsserverschlüssel im Crypto-Key-Header als URL-sicherer base64-codierter String mit vorangestelltem p256ecdsa= gesendet werden muss.
Crypto-Key: p256ecdsa=[URL Safe Base64 Public Application Server Key]
Die Nutzlastverschlüsselung
Als Nächstes sehen wir uns an, wie wir eine Nutzlast mit einer Push-Nachricht senden können, damit unsere Web-App auf die empfangenen Daten zugreifen kann, wenn sie eine Push-Nachricht erhält.
Eine häufige Frage, die sich bei der Verwendung anderer Push-Dienste stellt, ist, warum die Web-Push-Nutzlast verschlüsselt werden muss. Bei systemeigenen Apps können Push-Nachrichten Daten als Nur-Text senden.
Das Schöne an Web-Push ist, dass alle Push-Dienste dieselbe API (das Web-Push-Protokoll) verwenden. Entwickler müssen sich also nicht darum kümmern, welcher Push-Dienst verwendet wird. Wir können eine Anfrage im richtigen Format stellen und erwarten, dass eine Push-Nachricht gesendet wird. Der Nachteil ist, dass Entwickler Nachrichten an einen Push-Dienst senden könnten, der nicht vertrauenswürdig ist. Durch die Verschlüsselung der Nutzlast kann ein Push-Dienst die gesendeten Daten nicht lesen. Nur der Browser kann die Informationen entschlüsseln. So werden die Daten des Nutzers geschützt.
Die Verschlüsselung der Nutzlast ist in der Spezifikation zur Nachrichtenverschlüsselung definiert.
Bevor wir uns die einzelnen Schritte zum Verschlüsseln der Nutzlast einer Push-Nachricht ansehen, sollten wir uns mit einigen Techniken vertraut machen, die während des Verschlüsselungsprozesses verwendet werden. (Vielen Dank an Mat Scales für seinen hervorragenden Artikel zur Push-Verschlüsselung.)
ECDH und HKDF
Sowohl ECDH als auch HKDF werden im gesamten Verschlüsselungsprozess verwendet und bieten Vorteile für die Verschlüsselung von Informationen.
ECDH: Elliptic Curve Diffie-Hellman-Schlüsselaustausch
Stellen Sie sich vor, Sie haben zwei Personen, die Informationen austauschen möchten, Alice und Bob. Sowohl Alice als auch Bob haben ihre eigenen öffentlichen und privaten Schlüssel. Alice und Bob teilen ihre öffentlichen Schlüssel miteinander.
Die nützliche Eigenschaft von mit ECDH generierten Schlüsseln ist, dass Alice ihren privaten Schlüssel und Bobs öffentlichen Schlüssel verwenden kann, um den geheimen Wert „X“ zu erstellen. Bob kann dasselbe tun und mit seinem privaten Schlüssel und dem öffentlichen Schlüssel von Alice unabhängig denselben Wert „X“ erstellen. Dadurch wird „X“ zu einem gemeinsamen Geheimnis und Alice und Bob mussten nur ihren öffentlichen Schlüssel teilen. Jetzt können Bob und Alice „X“ verwenden, um Nachrichten zwischen ihnen zu verschlüsseln und zu entschlüsseln.
Soweit ich weiß, definiert ECDH die Eigenschaften von Kurven, die diese „Funktion“ zum Erstellen eines gemeinsamen Secrets „X“ ermöglichen.
Dies ist eine allgemeine Erklärung von ECDH. Wenn Sie mehr erfahren möchten, empfehlen wir Ihnen, sich dieses ausführlichere ECDH-Übersichtsvideo anzusehen.
In Bezug auf den Code: Die meisten Sprachen/Plattformen enthalten Bibliotheken, mit denen sich diese Schlüssel einfach generieren lassen.
In Node würden wir Folgendes tun:
const keyCurve = crypto.createECDH('prime256v1');
keyCurve.generateKeys();
const publicKey = keyCurve.getPublicKey();
const privateKey = keyCurve.getPrivateKey();
HKDF: HMAC-basierte Schlüsselableitungsfunktion
Wikipedia bietet eine kurze Beschreibung von HKDF:
HKDF ist eine HMAC-basierte Schlüsselableitungsfunktion, die schwaches Schlüsselmaterial in kryptografisch starkes Schlüsselmaterial umwandelt. Sie kann beispielsweise verwendet werden, um über Diffie-Hellman ausgetauschte gemeinsame Secrets in Schlüsselmaterial umzuwandeln, das für die Verschlüsselung, Integritätsprüfung oder Authentifizierung geeignet ist.
Im Wesentlichen nimmt HKDF eine Eingabe, die nicht besonders sicher ist, und macht sie sicherer.
Die Spezifikation, die diese Verschlüsselung definiert, erfordert die Verwendung von SHA-256 als Hash-Algorithmus. Die resultierenden Schlüssel für HKDF in Web-Push-Benachrichtigungen dürfen nicht länger als 256 Bit (32 Byte) sein.
In Node könnte dies so implementiert werden:
// Simplified HKDF, returning keys up to 32 bytes long
function hkdf(salt, ikm, info, length) {
// Extract
const keyHmac = crypto.createHmac('sha256', salt);
keyHmac.update(ikm);
const key = keyHmac.digest();
// Expand
const infoHmac = crypto.createHmac('sha256', key);
infoHmac.update(info);
// A one byte long buffer containing only 0x01
const ONE_BUFFER = new Buffer(1).fill(1);
infoHmac.update(ONE_BUFFER);
return infoHmac.digest().slice(0, length);
}
Dieser Beispielcode stammt aus dem Artikel von Mat Scale.
Dies umfasst grob ECDH und HKDF.
ECDH ist eine sichere Methode, um öffentliche Schlüssel zu teilen und ein gemeinsames Secret zu generieren. HKDF ist eine Möglichkeit, unsicheres Material sicher zu machen.
Dieser wird bei der Verschlüsselung unserer Nutzlast verwendet. Sehen wir uns als Nächstes an, was wir als Eingabe verwenden und wie diese verschlüsselt wird.
Eingaben
Wenn wir eine Push-Nachricht mit einer Nutzlast an einen Nutzer senden möchten, benötigen wir drei Eingaben:
- Die Nutzlast selbst.
- Das Secret
authaus demPushSubscription. - Der
p256dh-Schlüssel aus derPushSubscription.
Wir haben gesehen, wie die Werte auth und p256dh aus einem PushSubscription abgerufen werden. Hier noch einmal zur Erinnerung: Für ein Abo benötigen wir diese Werte:
subscription.toJSON().keys.auth;
subscription.toJSON().keys.p256dh;
subscription.getKey('auth');
subscription.getKey('p256dh');
Der Wert auth sollte als Secret behandelt und nicht außerhalb Ihrer Anwendung weitergegeben werden.
Der Schlüssel p256dh ist ein öffentlicher Schlüssel, der manchmal auch als öffentlicher Clientschlüssel bezeichnet wird. Hier bezeichnen wir p256dh als den öffentlichen Schlüssel des Abos. Der öffentliche Schlüssel des Abos wird vom Browser generiert. Der Browser hält den privaten Schlüssel geheim und verwendet ihn zum Entschlüsseln der Nutzlast.
Diese drei Werte, auth, p256dh und payload, werden als Eingaben benötigt. Das Ergebnis des Verschlüsselungsprozesses ist die verschlüsselte Nutzlast, ein Salt-Wert und ein öffentlicher Schlüssel, der nur zum Verschlüsseln der Daten verwendet wird.
Salt
Der Salt muss aus 16 Byte zufälligen Daten bestehen. In NodeJS würden wir so einen Salt erstellen:
const salt = crypto.randomBytes(16);
Öffentliche/private Schlüssel
Die öffentlichen und privaten Schlüssel sollten mit einer elliptischen P-256-Kurve generiert werden. In Node sieht das so aus:
const localKeysCurve = crypto.createECDH('prime256v1');
localKeysCurve.generateKeys();
const localPublicKey = localKeysCurve.getPublicKey();
const localPrivateKey = localKeysCurve.getPrivateKey();
Diese Schlüssel werden als „lokale Schlüssel“ bezeichnet. Sie werden nur für die Verschlüsselung verwendet und haben nichts mit Anwendungsserverschlüsseln zu tun.
Mit der Nutzlast, dem Authentifizierungs-Secret und dem öffentlichen Schlüssel des Abos als Eingaben sowie einem neu generierten Salt und einem Satz lokaler Schlüssel können wir nun die Verschlüsselung vornehmen.
Gemeinsames Secret
Im ersten Schritt wird ein gemeinsames Secret mit dem öffentlichen Schlüssel des Abos und unserem neuen privaten Schlüssel erstellt. Erinnern Sie sich an die ECDH-Erklärung mit Alice und Bob? Einfach so.
const sharedSecret = localKeysCurve.computeSecret(
subscription.keys.p256dh,
'base64',
);
Dieser wird im nächsten Schritt zur Berechnung des pseudozufälligen Schlüssels (PRK) verwendet.
Pseudozufälliger Schlüssel
Der pseudozufällige Schlüssel (PRK) ist die Kombination aus dem Auth-Secret des Push-Abos und dem gemeinsamen Secret, das wir gerade erstellt haben.
const authEncBuff = new Buffer('Content-Encoding: auth\0', 'utf8');
const prk = hkdf(subscription.keys.auth, sharedSecret, authEncBuff, 32);
Sie fragen sich vielleicht, wofür der String Content-Encoding: auth\0 gedacht ist.
Kurz gesagt, es hat keinen klaren Zweck, obwohl Browser eine eingehende Nachricht entschlüsseln und nach der erwarteten Inhaltscodierung suchen könnten.
\0 fügt am Ende des Buffers ein Byte mit dem Wert 0 hinzu. Dies wird von Browsern erwartet, die die Nachricht entschlüsseln. Sie erwarten eine bestimmte Anzahl von Byte für die Inhaltscodierung, gefolgt von einem Byte mit dem Wert 0 und den verschlüsselten Daten.
Unser pseudozufälliger Schlüssel führt einfach die Authentifizierung, das gemeinsame Secret und einen Teil der Codierungsinformationen über HKDF aus (wodurch er kryptografisch stärker wird).
Kontext
Der „Kontext“ ist ein Satz von Byte, der später im Verschlüsselungsbrowser zur Berechnung von zwei Werten verwendet wird. Es handelt sich im Wesentlichen um ein Byte-Array, das den öffentlichen Schlüssel des Abos und den lokalen öffentlichen Schlüssel enthält.
const keyLabel = new Buffer('P-256\0', 'utf8');
// Convert subscription public key into a buffer.
const subscriptionPubKey = new Buffer(subscription.keys.p256dh, 'base64');
const subscriptionPubKeyLength = new Uint8Array(2);
subscriptionPubKeyLength[0] = 0;
subscriptionPubKeyLength[1] = subscriptionPubKey.length;
const localPublicKeyLength = new Uint8Array(2);
subscriptionPubKeyLength[0] = 0;
subscriptionPubKeyLength[1] = localPublicKey.length;
const contextBuffer = Buffer.concat([
keyLabel,
subscriptionPubKeyLength.buffer,
subscriptionPubKey,
localPublicKeyLength.buffer,
localPublicKey,
]);
Der endgültige Kontextpuffer ist ein Label, die Anzahl der Byte im öffentlichen Schlüssel des Abos, gefolgt vom Schlüssel selbst, dann die Anzahl der Byte im lokalen öffentlichen Schlüssel, gefolgt vom Schlüssel selbst.
Mit diesem Kontextwert können wir eine Nonce und einen Content Encryption Key (CEK) erstellen.
Inhaltsverschlüsselungsschlüssel und Nonce
Eine Nonce ist ein Wert, der Replay-Angriffe verhindert, da er nur einmal verwendet werden sollte.
Der Inhaltsverschlüsselungsschlüssel (Content Encryption Key, CEK) ist der Schlüssel, der letztendlich zum Verschlüsseln der Nutzlast verwendet wird.
Zuerst müssen wir die Datenbytes für die Nonce und den CEK erstellen. Das ist einfach ein String für die Inhaltsverschlüsselung, gefolgt vom Kontextpuffer, den wir gerade berechnet haben:
const nonceEncBuffer = new Buffer('Content-Encoding: nonce\0', 'utf8');
const nonceInfo = Buffer.concat([nonceEncBuffer, contextBuffer]);
const cekEncBuffer = new Buffer('Content-Encoding: aesgcm\0');
const cekInfo = Buffer.concat([cekEncBuffer, contextBuffer]);
Diese Informationen werden über HKDF verarbeitet, wobei Salt und PRK mit „nonceInfo“ und „cekInfo“ kombiniert werden:
// The nonce should be 12 bytes long
const nonce = hkdf(salt, prk, nonceInfo, 12);
// The CEK should be 16 bytes long
const contentEncryptionKey = hkdf(salt, prk, cekInfo, 16);
Dadurch erhalten wir unsere Nonce und den Schlüssel für die Inhaltsverschlüsselung.
Verschlüsselung durchführen
Da wir jetzt unseren Inhaltsverschlüsselungsschlüssel haben, können wir die Nutzlast verschlüsseln.
Wir erstellen eine AES128-Verschlüsselung mit dem Inhaltsschlüssel als Schlüssel und der Nonce als Initialisierungsvektor.
In Node sieht das so aus:
const cipher = crypto.createCipheriv(
'id-aes128-GCM',
contentEncryptionKey,
nonce,
);
Bevor wir die Nutzlast verschlüsseln, müssen wir festlegen, wie viel Padding wir am Anfang der Nutzlast hinzufügen möchten. Der Grund, warum wir Padding hinzufügen möchten, ist, dass dadurch verhindert wird, dass Unbefugte anhand der Nutzlastgröße „Typen“ von Nachrichten bestimmen können.
Sie müssen zwei Byte Padding hinzufügen, um die Länge des zusätzlichen Paddings anzugeben.
Wenn Sie beispielsweise kein Padding hinzugefügt haben, haben Sie zwei Byte mit dem Wert 0, d. h. es ist kein Padding vorhanden. Nach diesen beiden Byte wird die Nutzlast gelesen. Wenn Sie 5 Byte Padding hinzugefügt haben, haben die ersten beiden Byte den Wert 5. Der Consumer liest dann weitere 5 Byte und beginnt dann mit dem Lesen der Nutzlast.
const padding = new Buffer(2 + paddingLength);
// The buffer must be only zeros, except the length
padding.fill(0);
padding.writeUInt16BE(paddingLength, 0);
Anschließend werden das Padding und die Nutzlast durch diese Chiffre geleitet.
const result = cipher.update(Buffer.concat(padding, payload));
cipher.final();
// Append the auth tag to the result -
// https://nodejs.org/api/crypto.html#crypto_cipher_getauthtag
const encryptedPayload = Buffer.concat([result, cipher.getAuthTag()]);
Wir haben jetzt unsere verschlüsselte Nutzlast. Super!
Jetzt müssen Sie nur noch festlegen, wie diese Nutzlast an den Push-Dienst gesendet wird.
Verschlüsselte Header und Text der Nutzlast
Um diese verschlüsselte Nutzlast an den Push-Dienst zu senden, müssen wir in unserer POST-Anfrage einige verschiedene Header definieren.
Verschlüsselungsheader
Der Header „Encryption“ muss den Salt enthalten, der zum Verschlüsseln der Nutzlast verwendet wird.
Der 16-Byte-Salt sollte base64-URL-sicher codiert und dem Verschlüsselungsheader hinzugefügt werden, z. B.:
Encryption: salt=[URL Safe Base64 Encoded Salt]
Crypto-Key-Header
Wir haben gesehen, dass der Header Crypto-Key im Abschnitt „Application Server Keys“ verwendet wird, um den öffentlichen Anwendungsserverschlüssel zu enthalten.
Dieser Header wird auch verwendet, um den lokalen öffentlichen Schlüssel freizugeben, der zum Verschlüsseln der Nutzlast verwendet wird.
Der resultierende Header sieht so aus:
Crypto-Key: dh=[URL Safe Base64 Encoded Local Public Key String]; p256ecdsa=[URL Safe Base64 Encoded Public Application Server Key]
Header für Inhaltstyp, Länge und Codierung
Der Header Content-Length ist die Anzahl der Byte in der verschlüsselten Nutzlast. Die Header „Content-Type“ und „Content-Encoding“ sind feste Werte.
Dies wird unten dargestellt.
Content-Length: [Number of Bytes in Encrypted Payload]
Content-Type: 'application/octet-stream'
Content-Encoding: 'aesgcm'
Nachdem diese Header festgelegt wurden, müssen wir die verschlüsselte Nutzlast als Text der Anfrage senden. Beachten Sie, dass Content-Type auf application/octet-stream festgelegt ist. Das liegt daran, dass die verschlüsselte Nutzlast als Bytestream gesendet werden muss.
In NodeJS würden wir das so machen:
const pushRequest = https.request(httpsOptions, function(pushResponse) {
pushRequest.write(encryptedPayload);
pushRequest.end();
Mehr Header?
Wir haben die Header für JWT-/Anwendungsserverschlüssel (d.h. wie die Anwendung beim Push-Dienst identifiziert wird) und die Header für das Senden einer verschlüsselten Nutzlast behandelt.
Es gibt zusätzliche Header, mit denen Push-Dienste das Verhalten gesendeter Nachrichten ändern. Einige dieser Header sind erforderlich, andere sind optional.
TTL-Header
Erforderlich
TTL (oder „time to live“) ist eine Ganzzahl, die die Anzahl der Sekunden angibt, die Ihre Push-Nachricht im Push-Dienst verbleiben soll, bevor sie zugestellt wird. Wenn die TTL abläuft, wird die Nachricht aus der Warteschlange des Push-Dienstes entfernt und nicht zugestellt.
TTL: [Time to live in seconds]
Wenn Sie für TTL den Wert „0“ festlegen, versucht der Push-Dienst, die Nachricht sofort zuzustellen. Wenn das Gerät jedoch nicht erreichbar ist, wird die Nachricht sofort aus der Warteschlange des Push-Dienstes entfernt.
Technisch gesehen kann ein Push-Dienst die TTL einer Push-Nachricht reduzieren, wenn er möchte. Ob dies der Fall ist, können Sie anhand des Headers TTL in der Antwort eines Push-Dienstes feststellen.
Thema
Optional
Themen sind Strings, mit denen ausstehende Nachrichten durch eine neue Nachricht ersetzt werden können, wenn sie übereinstimmende Themennamen haben.
Das ist nützlich, wenn mehrere Nachrichten gesendet werden, während ein Gerät offline ist, und Sie möchten, dass ein Nutzer nur die neueste Nachricht sieht, wenn das Gerät eingeschaltet wird.
Dringlichkeit
Optional
Die Dringlichkeit gibt dem Push-Dienst an, wie wichtig eine Nachricht für den Nutzer ist. Der Push-Dienst kann damit die Akkulaufzeit des Geräts eines Nutzers verlängern, indem er es bei niedrigem Akkustand nur für wichtige Nachrichten aktiviert.
Der Headerwert wird wie unten dargestellt definiert. Der Standardwert ist normal
Urgency: [very-low | low | normal | high]
Alles zusammen
Wenn Sie weitere Fragen zur Funktionsweise haben, können Sie sich jederzeit in der web-push-libs-Organisation ansehen, wie Bibliotheken Push-Benachrichtigungen auslösen.
Sobald Sie eine verschlüsselte Nutzlast und die oben genannten Header haben, müssen Sie nur noch eine POST-Anfrage an die endpoint in einer PushSubscription senden.
Was machen wir also mit der Antwort auf diese POST-Anfrage?
Antwort vom Push-Dienst
Nachdem du eine Anfrage an einen Push-Dienst gesendet hast, musst du den Statuscode der Antwort prüfen, um festzustellen, ob die Anfrage erfolgreich war.
| Statuscode | Beschreibung |
|---|---|
| 201 | Erstellt Die Anfrage zum Senden einer Push-Nachricht wurde empfangen und akzeptiert. |
| 429 | Zu viele Anfragen. Das bedeutet, dass Ihr Anwendungsserver ein Ratenlimit bei einem Push-Dienst erreicht hat. Der Push-Dienst sollte einen „Retry-After“-Header enthalten, der angibt, wie lange es dauert, bis eine weitere Anfrage gestellt werden kann. |
| 400 | Ungültige Anfrage. Das bedeutet in der Regel, dass einer Ihrer Header ungültig oder falsch formatiert ist. |
| 404 | Nicht gefunden. Dies ist ein Hinweis darauf, dass das Abo abgelaufen ist und nicht verwendet werden kann. In diesem Fall sollten Sie die `PushSubscription` löschen und warten, bis der Client den Nutzer erneut abonniert. |
| 410 | Nicht mehr vorhanden. Das Abo ist nicht mehr gültig und sollte vom Anwendungsserver entfernt werden. Dies kann durch Aufrufen von `unsubscribe()` für ein `PushSubscription` reproduziert werden. |
| 413 | Nutzlastgröße zu groß. Die Mindestgröße der Nutzlast, die ein Push-Dienst unterstützen muss, beträgt 4.096 Byte (oder 4 KB). |
Weitere Informationen zu den HTTP-Statuscodes finden Sie im Web Push-Standard (RFC8030).
Weitere Informationen
- Web-Push-Benachrichtigungen – Übersicht
- Funktionsweise von Push
- Nutzer abonnieren
- UX für Berechtigungen
- Nachrichten mit Web-Push-Bibliotheken senden
- Web-Push-Protokoll
- Push-Ereignisse verarbeiten
- Benachrichtigung anzeigen
- Benachrichtigungsverhalten
- Häufige Benachrichtigungsmuster
- Häufig gestellte Fragen zu Push-Benachrichtigungen
- Häufige Probleme und Fehler melden