Protokół Web Push Protocol

Wiemy już, jak za pomocą biblioteki można wywoływać wiadomości push, ale do czego właściwie służą te biblioteki?

Wysyłają żądania do sieci, dbając o to, aby były one w odpowiednim formacie. Specyfikacja, która definiuje to żądanie sieciowe, to Web Push Protocol.

Schemat wysyłania powiadomienia push z serwera do usługi przesyłania powiadomień push

W tej sekcji opisano, jak serwer może się identyfikować za pomocą kluczy serwera aplikacji oraz jak wysyłane są zaszyfrowane dane i powiązane z nimi dane.

Nie jest to najlepsza strona web push i nie jestem ekspertem od szyfrowania, ale przyjrzyjmy się bliżej poszczególnym elementom, ponieważ warto wiedzieć, co te biblioteki robią w tle.

Klucze serwera aplikacji

Gdy subskrybujemy użytkownika, przekazujemy applicationServerKey. Ten klucz jest przekazywany usłudze push i służy do sprawdzania, czy aplikacja, do której użytkownik się zapisał, jest też aplikacją, która uruchamia wiadomości push.

Gdy aktywujemy wiadomość push, wysyłamy zestaw nagłówków, które pozwalają usłudze push uwierzytelnić aplikację. Jest to zdefiniowane w specyfikacji VAPID.

Co to wszystko oznacza i co się dokładnie dzieje? Oto czynności podejmowane w ramach uwierzytelniania serwera aplikacji:

  1. Serwer aplikacji podpisuje niektóre informacje JSON za pomocą klucza aplikacji prywatnej.
  2. Te podpisane informacje są wysyłane do usługi push jako nagłówek w żądaniu POST.
  3. Usługa push używa przechowywanego klucza publicznego otrzymanego odpushManager.subscribe(), aby sprawdzić, czy otrzymane informacje są podpisane kluczem prywatnym powiązanym z kluczem publicznym. Pamiętaj: kluczem publicznym jest applicationServerKey przekazywany do wywołania subskrypcji.
  4. Jeśli podpisane informacje są prawidłowe, usługa push wysyła wiadomość push do użytkownika.

Poniżej znajdziesz przykład przepływu informacji. (zwróć uwagę na legendę w lewym dolnym rogu, która wskazuje klucze publiczne i prywatne).

Ilustracja pokazująca, jak prywatny klucz serwera aplikacji jest używany podczas wysyłania wiadomości

„Podpisane informacje” dodane do nagłówka w żądaniu to token internetowy JSON.

Token sieciowy JSON

Token sieciowy JSON (w skrócie JWT) to sposób na wysłanie wiadomości do osoby trzeciej, aby odbiorca mógł zweryfikować, kto ją wysłał.

Gdy zewnętrzny odbiorca otrzyma wiadomość, musi uzyskać klucz publiczny nadawcy i użyć go do zweryfikowania podpisu tokena JWT. Jeśli podpis jest prawidłowy, token JWT musi być podpisany odpowiednim kluczem prywatnym, a więc musi pochodzić od oczekiwanego nadawcy.

Na stronie https://jwt.io/ znajduje się wiele bibliotek, które mogą wykonać podpisywanie za Ciebie. Zalecamy zrobić to tam, gdzie to możliwe. Dla pewności zobaczmy, jak ręcznie utworzyć podpisany token JWT.

Web push i podpisane tokeny JWT

Podpisany token JWT to tylko ciąg znaków, ale można go traktować jako 3 ciągi połączone kropkami.

Ilustracja przedstawiająca ciągi tekstowe w tokenie internetowym JSON

Pierwszy i drugi ciąg znaków (informacje JWT i dane JWT) to fragmenty danych JSON zakodowane w formacie base64, co oznacza, że są one dostępne do odczytu publicznie.

Pierwszy ciąg znaków zawiera informacje o samym JWT, wskazujące, który algorytm został użyty do utworzenia podpisu.

Informacje JWT dla powiadomień web push muszą zawierać te dane:

{
  "typ": "JWT",
  "alg": "ES256"
}

Drugi ciąg to dane JWT. Zawiera informacje o nadawcy tokena JWT, jego odbiorcy i czasie ważności.

W przypadku web push dane mają taki format:

{
  "aud": "https://some-push-service.org",
  "exp": "1469618703",
  "sub": "mailto:example@web-push-book.org"
}

Wartość aud to „grupa odbiorców”, czyli osoby, do których jest przeznaczony token JWT. W przypadku web push odbiorcami jest usługa push, więc ustawiamy ją jako źródło usługi push.

Wartość exp to data wygaśnięcia tokena JWT. Zapobiega to ponownemu wykorzystaniu tokena JWT przez szpiegów, jeśli zostanie on przechwycony. Czas wygaśnięcia to sygnatura czasowa w sekundach, która nie może być dłuższa niż 24 godziny.

W Node.js data ważności jest ustawiana za pomocą:

Math.floor(Date.now() / 1000) + 12 * 60 * 60;

Jest to 12 godzin, a nie 24 godziny, aby uniknąć problemów z różnicami zegara między aplikacją wysyłającą a usługą push.

Na koniec wartością sub musi być URL lub mailto. Dzięki temu jeśli usługa push musi skontaktować się z nadawcą, może znaleźć informacje kontaktowe z tokena JWT. (Właśnie dlatego biblioteka webpush wymagała adresu e-mail).

Podobnie jak informacje JWT, dane JWT są kodowane jako ciąg tekstowy w formacie base64 przeznaczonym do bezpiecznego przesyłania w adresie URL.

Trzeci ciąg znaków, czyli podpis, jest wynikiem połączenia dwóch pierwszych ciągów znaków (informacji JWT i danych JWT) za pomocą znaku kropki. Nazywamy go „niepodpisanym tokenem”.

Proces podpisywania wymaga zaszyfrowania „niepodpisanego tokena” za pomocą algorytmu ES256. Zgodnie ze specyfikacją JWT ES256 to skrót od „ECDSA z użyciem krzywej P-256 i algorytmu szyfrowania SHA-256”. Za pomocą szyfrowania w internecie możesz utworzyć podpis w ten sposób:

// 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);
});

Usługa push może zweryfikować token JWT za pomocą klucza publicznego serwera aplikacji w celu odszyfrowania podpisu i upewnić się, że odszyfrowany ciąg jest taki sam jak „niepodpisany token” (tzn. pierwsze 2 ciągi tokena JWT).

Podpisany token JWT (czyli wszystkie 3 ciągi znaków połączone kropkami) jest wysyłany do usługi web push jako nagłówek Authorization z dołączonym nagłówkiem WebPush, np.:

Authorization: 'WebPush [JWT Info].[JWT Data].[Signature]';

Protokół Web Push określa też, że klucz publiczny serwera aplikacji musi być wysyłany w nagłówku Crypto-Key jako ciąg znaków zakodowany w formacie base64 z przedrostem p256ecdsa=.

Crypto-Key: p256ecdsa=[URL Safe Base64 Public Application Server Key]

Szyfrowanie ładunku

Teraz przyjrzymy się, jak można wysłać ładunek za pomocą komunikatu push, aby aplikacja internetowa, która otrzyma wiadomość push, miała dostęp do otrzymanych danych.

Osoby, które korzystały z innych usług przesyłania powiadomień push, często zadają pytanie, dlaczego dane przesyłane przez internet muszą być szyfrowane. W przypadku aplikacji natywnych powiadomienia push mogą wysyłać dane w postaci zwykłego tekstu.

Jedną z zalet web push jest to, że wszystkie usługi push korzystają z tego samego interfejsu API (protokołu web push), więc deweloperzy nie muszą się martwić, do kogo należy dana usługa push. Możemy wysłać żądanie w odpowiednim formacie i oczekiwać, że zostanie wysłana wiadomość push. Wadą jest to, że deweloperzy mogą wysyłać wiadomości do niezaufanej usługi push. Dzięki zaszyfrowaniu ładunku usługa push nie może odczytać wysłanych danych. Tylko przeglądarka może odszyfrować informacje. Dzięki temu dane użytkownika są chronione.

Szyfrowanie ładunku jest zdefiniowane w specyfikacji szyfrowania wiadomości.

Zanim przyjrzymy się konkretnym krokom szyfrowania ładunku wiadomości push, przyjrzymy się kilku technikom, które zostaną użyte podczas tego procesu. (Dziękujemy Matowi Scalesowi za jego świetny artykuł na temat szyfrowania push).

ECDH i HKDF

Zarówno ECDH, jak i HKDF są używane w trakcie całego procesu szyfrowania i oferują korzyści w zakresie szyfrowania informacji.

ECDH: wymiana kluczy Diffiego-Hellmana na krzywej eliptycznej

Wyobraź sobie, że masz dwie osoby, które chcą podzielić się informacjami: Alicję i Roberta. Zarówno Alicja, jak i Robert mają własne klucze publiczne i prywatne. Alicja i Robert udostępniają sobie klucze publiczne.

Przydatną właściwością kluczy wygenerowanych za pomocą ECDH jest to, że Alice może użyć swojego klucza prywatnego i klucza publicznego Boba, aby utworzyć tajną wartość „X”. Robert może zrobić to samo, używając klucza prywatnego i klucza publicznego Alicji, aby niezależnie utworzyć tę samą wartość „X”. Dzięki temu „X” staje się wspólnym sekretem, a Alicja i Robert musieli udostępnić tylko swój klucz publiczny. Teraz Robert i Alicja mogą używać „X” do szyfrowania i odszyfrowywania wiadomości przesyłanych między nimi.

O ile mi wiadomo, ECDH definiuje właściwości krzywych, które umożliwiają tę „funkcję” tworzenia wspólnego tajnego klucza „X”.

To jest ogólne omówienie ECDH. Jeśli chcesz dowiedzieć się więcej, zachęcam do obejrzenia tego filmu.

Jeśli chodzi o kod – większość języków / platform zawiera biblioteki, które ułatwiają generowanie tych kluczy.

W węźle:

const keyCurve = crypto.createECDH('prime256v1');
keyCurve.generateKeys();

const publicKey = keyCurve.getPublicKey();
const privateKey = keyCurve.getPrivateKey();

HKDF: funkcja derywacji klucza oparta na HMAC

Wikipedia zawiera krótki opis HKDF:

HKDF to oparta na HMAC funkcja derywacji kluczy, która przekształca każdy słaby materiał klucza w materiał klucza o wysokim stopniu kryptografii. Można go na przykład użyć do przekształcenia wygenerowanych kluczy tajnych Diffie-Hellmana w klucze nadające się do szyfrowania, sprawdzania integralności lub uwierzytelniania.

Zasadniczo HKDF pobiera dane, które nie są szczególnie bezpieczne, i zwiększa ich bezpieczeństwo.

Specyfikacja definiująca to szyfrowanie wymaga użycia algorytmu SHA-256 jako algorytmu haszującego, a klucze uzyskane w przypadku HKDF w ramach web push nie powinny być dłuższe niż 256 bitów (32 bajty).

W węźle można to zaimplementować w ten sposób:

// 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);
}

Przykładowy kod pochodzi z artykułu Mat Scale'a.

Dotyczy to w ogólnym zarysie ECDHHKDF.

ECDH to bezpieczny sposób udostępniania kluczy publicznych i generowania udostępnionego klucza tajnego. HKDF to sposób na przekształcenie niezabezpieczonych materiałów w bezpieczne.

Będzie on używany podczas szyfrowania ładunku. Teraz przyjrzyjmy się temu, co bierzemy pod uwagę jako dane wejściowe i jak je szyfrujemy.

Dane wejściowe

Aby wysłać użytkownikowi wiadomość push z ładunkiem, potrzebujemy 3 elementów:

  1. Payload.
  2. Obiekt tajny auth z poziomu PushSubscription.
  3. Klucz p256dh z urządzenia PushSubscription.

Zaobserwowaliśmy, że wartości auth i p256dh są pobierane z PushSubscription, ale dla przypomnienia, bo w przypadku subskrypcji potrzebne są te wartości:

subscription.toJSON().keys.auth;
subscription.toJSON().keys.p256dh;

subscription.getKey('auth');
subscription.getKey('p256dh');

Wartość auth powinna być traktowana jako tajna i nie powinna być udostępniana poza Twoją aplikacją.

Klucz p256dh jest kluczem publicznym, który czasami nazywany jest kluczem publicznym klienta. Tutaj będziemy nazywać p256dh kluczem publicznym subskrypcji. Klucz publiczny subskrypcji jest generowany przez przeglądarkę. Przeglądarka zachowa tajny klucz prywatny i użyje go do odszyfrowywania ładunku.

Te 3 wartości: auth, p256dh i payload są potrzebne jako dane wejściowe, a wynik procesu szyfrowania będzie szyfrowanym ładunkiem, wartością soli i kluczem publicznym używanym tylko do szyfrowania danych.

Sól

Ciąg zaburzający musi mieć 16 bajtów losowych danych. Aby utworzyć sól w Node.js, wykonaj te czynności:

const salt = crypto.randomBytes(16);

Klucze publiczne i prywatne

Klucze publiczne i prywatne należy wygenerować przy użyciu krzywej eliptycznej P-256, którą robimy w Node.js:

const localKeysCurve = crypto.createECDH('prime256v1');
localKeysCurve.generateKeys();

const localPublicKey = localKeysCurve.getPublicKey();
const localPrivateKey = localKeysCurve.getPrivateKey();

Te klucze nazywamy „kluczami lokalnymi”. Służą one tylko do szyfrowania i nie mają nic wspólnego z kluczami serwera aplikacji.

Mając dane ładunku, tajny klucz uwierzytelniający i klucz publiczny subskrypcji jako dane wejściowe oraz nowo wygenerowaną sól i zestaw kluczy lokalnych, możemy przeprowadzić szyfrowanie.

Udostępniony klucz tajny

Pierwszym krokiem jest utworzenie tajnego klucza za pomocą klucza publicznego subskrypcji i nowego klucza prywatnego (pamiętasz wyjaśnienie ECDH z Alicją i Bobem? Tak po prostu.

const sharedSecret = localKeysCurve.computeSecret(
  subscription.keys.p256dh,
  'base64',
);

Będzie on używany w następnym kroku do obliczania pseudolosowego klucza (PRK).

Pseudolosowy klucz

Pseudolosowy klucz (PRK) to połączenie tajnego klucza uwierzytelniania subskrypcji push i udostępnionego obiektu tajnego, który właśnie utworzyliśmy.

const authEncBuff = new Buffer('Content-Encoding: auth\0', 'utf8');
const prk = hkdf(subscription.keys.auth, sharedSecret, authEncBuff, 32);

Zastanawiasz się pewnie, do czego służy ciąg tekstowy Content-Encoding: auth\0. Krótko mówiąc, nie ma to wyraźnego celu, chociaż przeglądarki mogą odszyfrować przychodzącą wiadomość i poszukać odpowiedniego kodowania treści. \0 dodaje bajt o wartości 0 na końcu bufora. Przeglądarki, które odszyfrowują wiadomość, oczekują takiej liczby bajtów na potrzeby kodowania treści, a następnie bajtu o wartości 0, a potem zaszyfrowanych danych.

Nasz klucz pseudolosowy po prostu uruchamia autoryzację, wspólny klucz tajny i część informacji kodowania za pomocą HKDF (czyli wzmacnia szyfrowanie).

Kontekst

„Kontekst” to zbiór bajtów, który służy do obliczania dwóch wartości w późniejszym etapie szyfrowania w przeglądarce. Jest to tablica bajtów zawierająca klucz publiczny subskrypcji i klucz publiczny lokalny.

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,
]);

Ostatni bufor kontekstu to etykieta, liczba bajtów w kluczu publicznym subskrypcji, po którym następuje sam klucz, liczba bajtów lokalnego klucza publicznego, a następnie sam klucz.

Dzięki tej wartości kontekstowej możemy jej użyć do utworzenia liczby jednorazowej i klucza szyfrowania treści (CEK).

Klucz szyfrowania treści i nonce

Numer losowy to wartość, która zapobiega atakom metodą powtórzenia, ponieważ powinna być użyta tylko raz.

Klucz szyfrujący dane (CEK) to klucz, który ostatecznie zostanie użyty do zaszyfrowania ładunku.

Najpierw musimy utworzyć bajty danych dla nonce i CEK, czyli po prostu ciąg znaków kodowania treści, po którym następuje obliczony przez nas bufor kontekstu:

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]);

Te informacje są sprawdzane przez HKDF, łącząc sól i PRK z wartościami nonceInfo i cekInfo:

// 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);

Daje nam to klucz jednorazowy i szyfrowanie treści.

Szyfrowanie

Teraz, gdy mamy klucz szyfrowania treści, możemy zaszyfrować ładunek.

Tworzymy szyfr AES128, w którym jako klucz używany jest klucz szyfrowania treści, a liczba jednorazowa to wektor inicjujący.

W Node wygląda to tak:

const cipher = crypto.createCipheriv(
  'id-aes128-GCM',
  contentEncryptionKey,
  nonce,
);

Zanim zaszyfrujemy ładunek, musimy określić, ile wypełniacza chcemy dodać na początku ładunku. Chcemy dodać wypełnienie, aby zapobiec ryzyku, że podsłuchujący będą mogli określić „typy” wiadomości na podstawie rozmiaru danych.

Aby wskazać długość dodatkowego dopełnienia, musisz dodać 2 bajty.

Jeśli na przykład nie dodasz dopełnienia, zostaną zapisane 2 bajty z wartością 0, czyli brak dopełnienia. Po tych 2 bajtach odczytasz ładunek. Jeśli dodasz 5 bajtów wypełnienia, pierwsze 2 bajty będą miały wartość 5, więc konsument odczyta 5 dodatkowych bajtów, a potem rozpocznie odczyt ładunku.

const padding = new Buffer(2 + paddingLength);
// The buffer must be only zeros, except the length
padding.fill(0);
padding.writeUInt16BE(paddingLength, 0);

Następnie przesyłamy wypełnienie i ładunek za pomocą tego szyfru.

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()]);

Mamy już zaszyfrowany ładunek. Hura!

Pozostaje już tylko określić, w jaki sposób ładunek będzie wysyłany do usługi push.

Zaszyfrowane nagłówki i treść ładunku

Aby wysłać zaszyfrowane dane do usługi push, musimy zdefiniować kilka różnych nagłówków w żądaniu POST.

Nagłówek szyfrowania

Nagłówek „Encryption” musi zawierać sól użytą do zaszyfrowania ładunku.

Ten 16-bajtowy ciąg zaburzający powinien być zakodowany w bezpieczny sposób przy użyciu adresu URL w base64 i dodany do nagłówka Szyfrowanie w następujący sposób:

Encryption: salt=[URL Safe Base64 Encoded Salt]

Nagłówek Crypto-Key

Zauważyliśmy, że w sekcji „Klucze serwera aplikacji” jest używany nagłówek Crypto-Key, który zawiera publiczny klucz serwera aplikacji.

Służy on też do udostępniania lokalnego klucza publicznego używanego do szyfrowania ładunku.

Wygenerowany nagłówek wygląda tak:

Crypto-Key: dh=[URL Safe Base64 Encoded Local Public Key String]; p256ecdsa=[URL Safe Base64 Encoded Public Application Server Key]

Nagłówki typu treści, długości i kodowania

Nagłówek Content-Length to liczba bajtów w zaszyfrowanym ładunku. Nagłówki „Content-Type” i „Content-Encoding” mają wartości stałe. Poniżej możesz zobaczyć, jak to działa.

Content-Length: [Number of Bytes in Encrypted Payload]
Content-Type: 'application/octet-stream'
Content-Encoding: 'aesgcm'

Po ustawieniu tych nagłówków musimy wysłać zaszyfrowany ładunek jako treść żądania. Zwróć uwagę, że nagłówek Content-Type ma wartość application/octet-stream. Dzieje się tak, ponieważ zaszyfrowane dane muszą być wysyłane jako strumień bajtów.

W NodeJS zrobilibyśmy to tak:

const pushRequest = https.request(httpsOptions, function(pushResponse) {
pushRequest.write(encryptedPayload);
pushRequest.end();

Więcej nagłówków?

Omówiliśmy nagłówki używane w przypadku kluczy JWT i kluczy serwera aplikacji (np. jak identyfikować aplikację za pomocą usługi push) oraz nagłówki używane do wysyłania zaszyfrowanej treści ładunku.

Istnieją dodatkowe nagłówki, których używają usługi push, aby zmienić sposób działania wysyłanych wiadomości. Niektóre z tych nagłówków są wymagane, a inne opcjonalne.

Nagłówek TTL

Wymagany

TTL (lub czas życia) to liczba całkowita określająca liczbę sekund, przez jaką wiadomość push ma być dostępna w usłudze push, zanim zostanie dostarczona. Gdy TTL wygaśnie, wiadomość zostanie usunięta z kolejki usługi push i nie zostanie dostarczona.

TTL: [Time to live in seconds]

Jeśli ustawisz wartość TTL równą 0, usługa push spróbuje natychmiast dostarczyć wiadomość, ale jeśli nie uda się połączyć z urządzeniem, wiadomość zostanie natychmiast usunięta z kolejki usługi push.

Teoretycznie usługa push może zmniejszyć TTL wiadomości push, jeśli zechce to zrobić. Aby sprawdzić, czy tak się stało, sprawdź nagłówek TTL w odpowiedzi od usługi przesyłania danych.

Temat

Opcjonalny

Tematy to ciągi znaków, które można wykorzystać do zastąpienia oczekujących wiadomości nową wiadomością, jeśli mają one pasujące nazwy tematów.

Jest to przydatne w sytuacjach, gdy wysyłanych jest kilka wiadomości, gdy urządzenie jest offline, a chcesz, aby użytkownik widział tylko najnowszą wiadomość po włączeniu urządzenia.

Pilność

Opcjonalny

Pilność wskazuje usłudze powiadomień push, jak ważna jest wiadomość dla użytkownika. Usługa push może używać tej funkcji, aby oszczędzać czas pracy na baterii urządzenia użytkownika, budząc go tylko w przypadku ważnych wiadomości, gdy poziom naładowania baterii jest niski.

Wartość nagłówka jest zdefiniowana w sposób pokazany poniżej. Wartością domyślną jest normal.

Urgency: [very-low | low | normal | high]

Wszystko w jednym miejscu

Jeśli masz więcej pytań na temat tego, jak to działa, możesz sprawdzić, jak biblioteki wywołują wiadomości push na stronie web-push-libs.org.

Gdy masz już zaszyfrowany ładunek i wymienione powyżej nagłówki, wystarczy wysłać żądanie POST do endpoint w ramach PushSubscription.

Co zrobić z odpowiedzią na to żądanie POST?

Odpowiedź usługi push

Po wysłaniu żądania do usługi push musisz sprawdzić kod stanu odpowiedzi, aby dowiedzieć się, czy żądanie zostało zrealizowane.

Kod stanu Opis
201 Utworzono. Otrzymaliśmy i zaakceptowaliśmy prośbę o wysłanie powiadomienia push.
429 Zbyt wiele żądań. Oznacza to, że serwer aplikacji osiągnął limit szybkości w usłudze push. Usługa push powinna zawierać nagłówek „Ponów-After”, aby wskazać, po jakim czasie możliwe jest wysłanie kolejnego żądania.
400 Nieprawidłowe żądanie. Oznacza to zazwyczaj, że jeden z nagłówków jest nieprawidłowy lub ma nieprawidłowy format.
404 Nie znaleziono. Oznacza to, że subskrypcja wygasła i nie można z niej korzystać. W takim przypadku należy usunąć obiekt `PushSubscription` i poczekać, aż klient ponownie subskrybuje użytkownika.
410 Nie ma. Subskrypcja jest już nieważna i należy ją usunąć z serwera aplikacji. Można to odtworzyć, wywołując funkcję unsubscribe() w klasie PushSubscription.
413 Rozmiar ładunku jest zbyt duży. Minimalny rozmiar ładunku danych, który musi obsługiwać usługa push, to 4096 bajtów(lub 4 KB).

Więcej informacji o kodach stanu HTTP znajdziesz też w standardzie Web Push (RFC 8030).

Co dalej

Codelabs