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ą one żądania do sieci, dbając o to, aby były one w odpowiednim formacie. Specyfikacja, która definiuje to żądanie sieciowe, to protokół Web Push.

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 uruchamiamy powiadomienie push, wysyłamy zestaw nagłówków, które umożliwiają usłudze push uwierzytelnienie aplikacji. (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 od pushManager.subscribe(), aby sprawdzić, czy otrzymane informacje są podpisane kluczem prywatnym powiązanym z kluczem publicznym. Pamiętaj: klucz publiczny to applicationServerKey przekazany do wywołania subscribe.
  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 sieciowy JSON.

Token internetowy 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/ znajdziesz wiele bibliotek, które mogą wykonać podpisywanie za Ciebie. Zalecamy korzystanie z nich, gdy tylko 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 kierowany 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 zamiast 24 godzin, aby uniknąć problemów z różnicami czasowymi między aplikacją wysyłającą i usługą push.

Wartość sub musi być adresem URL lub adresem e-mail mailto. Dzięki temu, jeśli usługa push będzie musiała skontaktować się z nadawcą, będzie mogła znaleźć informacje kontaktowe w tokenie JWT. (dlatego biblioteka web-push 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 za pomocą krzywej P-256 i algorytmu haszującego SHA-256”. Za pomocą funkcji 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 przesyłania strumieniowego może weryfikować token JWT, używając klucza publicznego serwera aplikacji, aby odszyfrować podpis i upewnić się, że odszyfrowany ciąg znaków jest taki sam jak „niepodpisany token” (czyli pierwsze 2 ciągi znaków w tokenie 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

Następnie przyjrzyjmy się, jak wysłać ładunek z wiadomością push, aby nasza aplikacja internetowa mogła uzyskać dostęp do danych, gdy otrzyma wiadomość push.

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. Minusem jest to, że deweloperzy mogą wysyłać wiadomości do usługi przesyłania informacji push, która nie jest godna zaufania. 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 omówimy konkretne czynności związane z szyfrowaniem danych w wiadomościach push, omówimy kilka technik, które będą używane podczas procesu szyfrowania. (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

Załóżmy, że mamy 2 osoby, które chcą udostępnić informacje: Alicja i Robert. 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 swojego klucza prywatnego i klucza publicznego Alicji, aby niezależnie utworzyć tę samą wartość „X”. Dzięki temu „X” staje się wspólną tajemnicą, a Alicja i Bob 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 ogólne omówienie ECDH. Jeśli chcesz dowiedzieć się więcej, zachęcam do obejrzenia tego filmu.

W przypadku kodu większość języków i platform ma 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 funkcja derywacji klucza oparta na HMAC, która przekształca słaby materiał klucza w materiał klucza o silnych właściwościach kryptograficznych. 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 przyjmuje dane wejściowe, które nie są szczególnie bezpieczne, i czyni je bezpieczniejszymi.

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.

Wartości authp256dh zostały pobrane z poziomu tabeli PushSubscription. Przypominamy, że w przypadku subskrypcji potrzebujemy tych 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 to klucz publiczny, który czasami nazywa się kluczem publicznym klienta. Tutaj będziemy nazywać p256dh kluczem publicznym subskrypcji. Klucz publiczny subskrypcji jest generowany przez przeglądarkę. Przeglądarka będzie przechowywać klucz prywatny w tajemnicy i używać go do odszyfrowywania danych.

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 powinny być generowane za pomocą krzywej eliptycznej P-256, co w Node wygląda tak:

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 udziałem Alicji i Boba? Tak po prostu.

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

W następnym kroku służy on do obliczenia klucza pseudolosowego (PRK).

Klucz pseudolosowy

Klucz pseudolosowy (PRK) to kombinacja tajnego klucza autoryzacji subskrypcji push i wspólnego tajnego klucza, który właśnie został utworzony.

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 ona wyraźnego celu, ale przeglądarki mogą odszyfrować przychodzącą wiadomość i szukać oczekiwanego 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. 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, a następnie sam klucz.

Dzięki tej wartości kontekstu możemy użyć jej do utworzenia wartości losowej 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ą przetwarzane przez HKDF, który łączy sól i klucz PRK z informacjami 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);

Dzięki temu otrzymujemy klucz szyfrowania treści i klucz szyfrowania nonce.

Szyfrowanie

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

Tworzymy szyfr AES128, używając klucza szyfrowania treści jako klucza, a nonce jako wektora inicjującego.

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.

Musisz dodać 2 bajty wypełniacza, aby wskazać długość dodatkowego wypełniacza.

Jeśli np.nie dodasz wypełnienia, będą 2 bajty o wartości 0, co oznacza, że nie ma wypełnienia. Po tych 2 bajtach będziesz odczytywać ł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 tylko określić, jak przesłać ładunek do usługi push.

Zaszyfrowane nagłówki i treść ładunku

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

Nagłówek szyfrowania

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

Sól o długości 16 bajtów powinna być zakodowana w formacie base64 do wykorzystania w adresach URL i dodana do nagłówka szyfrowania w ten sposób:

Encryption: salt=[URL Safe Base64 Encoded Salt]

Nagłówek Crypto-Key

Zauważyliśmy, że nagłówek Crypto-Key jest używany w sekcji „Klucze serwera aplikacji” do przechowywania publicznego klucza serwera aplikacji.

Ten nagłówek służy też do udostępniania lokalnego klucza publicznego, który jest używany 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 przedstawiamy, jak to wygląda.

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 wysłać 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 informacji.

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 jak poniżej. Wartością domyślną jest normal.

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

Wszystko razem

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 przesyłania informacji push powinna zawierać nagłówek „Retry-After”, aby wskazać, po jakim czasie można wysłać kolejną prośbę.
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 jej używać. W takim przypadku należy usunąć obiekt `PushSubscription` i zaczekać, aż klient ponownie subskrybuje użytkownika.
410 Nie ma. Subskrypcja nie jest już waż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 za 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

Code labs