Protokół Web Push Protocol

Wiemy, że biblioteka może służyć do wywoływania wiadomości push, ale co dokładnie robią te biblioteki?

Wysyłają żądania sieciowe, dbając o to, aby miały one odpowiedni format. Specyfikacja, która definiuje to żądanie sieciowe, to Web Push Protocol.

Diagram wysyłania wiadomości push z serwera do usługi push.

W tej sekcji opisujemy, jak serwer może się identyfikować za pomocą kluczy serwera aplikacji oraz jak wysyłany jest zaszyfrowany ładunek i powiązane z nim dane.

Nie jest to najprzyjemniejsza strona powiadomień push w internecie, a ja nie jestem ekspertem od szyfrowania, ale przyjrzyjmy się poszczególnym elementom, ponieważ warto wiedzieć, co te biblioteki robią pod maską.

Klucze serwera aplikacji

Gdy subskrybujemy użytkownika, przekazujemy wartość applicationServerKey. Ten klucz jest przekazywany do usługi push i używany do sprawdzania, czy aplikacja, która zasubskrybowała użytkownika, jest również aplikacją, która wywołuje wiadomości push.

Gdy wysyłamy wiadomość push, przesył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 kroki uwierzytelniania serwera aplikacji:

  1. Serwer aplikacji podpisuje niektóre informacje w formacie JSON za pomocą prywatnego klucza aplikacji.
  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 tym kluczem publicznym. Pamiętaj: klucz publiczny to parametr applicationServerKey przekazywany do wywołania subskrypcji.
  4. Jeśli podpisane informacje są prawidłowe, usługa push wysyła wiadomość push do użytkownika.

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

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

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

Token internetowy JSON

Token sieciowy JSON (JWT) to sposób wysyłania wiadomości do firmy zewnętrznej, dzięki któremu odbiorca może sprawdzić, kto ją wysłał.

Gdy osoba trzecia otrzyma wiadomość, musi pobrać klucz publiczny nadawcy i użyć go do zweryfikowania podpisu tokena JWT. Jeśli podpis jest prawidłowy, token JWT musiał zostać podpisany pasującym kluczem prywatnym, a więc pochodzi od oczekiwanego nadawcy.

Na stronie jwt.io/ znajdziesz wiele bibliotek, które mogą wykonać za Ciebie podpisywanie. Zalecam korzystanie z nich, gdy tylko jest to możliwe. Dla pełności informacji zobaczmy, jak ręcznie utworzyć podpisany token JWT.

Powiadomienia push w internecie i podpisane tokeny JWT

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

Ilustracja ciągów znaków w tokenie internetowym JSON.

Pierwszy i drugi ciąg znaków (informacje o tokenie JWT i dane tokena JWT) to fragmenty kodu JSON zakodowane algorytmem Base64, co oznacza, że są publicznie czytelne.

Pierwszy ciąg znaków zawiera informacje o samym tokenie JWT, wskazujące, którego algorytmu użyto do utworzenia podpisu.

Informacje o tokenie JWT w przypadku powiadomień push w internecie muszą zawierać te dane:

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

Drugi ciąg znaków to dane tokena JWT. Zawiera informacje o nadawcy JWT, odbiorcy i okresie ważności.

W przypadku powiadomień push w internecie dane będą miały ten format:

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

Wartość aud to „odbiorca”, czyli podmiot, dla którego przeznaczony jest JWT. W przypadku powiadomień push w internecie odbiorcą jest usługa push, więc ustawiamy ją na źródło usługi push.

Wartość exp to data wygaśnięcia JWT. Zapobiega to ponownemu użyciu JWT przez osoby niepowołane, jeśli przechwycą one token. Czas wygaśnięcia to sygnatura czasowa w sekundach, która nie może być dłuższa niż 24 godziny.

W Node.js czas wygaśnięcia jest ustawiany za pomocą tego kodu:

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

Wynosi on 12 godzin, a nie 24, aby uniknąć problemów z różnicami w czasie między aplikacją wysyłającą a 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ą, znajdzie informacje kontaktowe w JWT. (Dlatego biblioteka powiadomień push w internecie potrzebowała adresu e-mail).

Podobnie jak informacje JWT, dane JWT są kodowane jako ciąg tekstowy w formacie base64 bezpiecznym dla adresu URL.

Trzeci ciąg znaków, czyli podpis, jest wynikiem połączenia pierwszych dwóch ciągów znaków (informacji o tokenie JWT i danych tokena JWT) za pomocą kropki. Ten ciąg znaków nazwiemy „niepodpisanym tokenem”. Następnie podpisujemy ten ciąg.

Proces podpisywania wymaga zaszyfrowania „niepodpisanego tokena” za pomocą algorytmu ES256. Zgodnie ze specyfikacją JWT ES256 to skrót od „ECDSA using the P-256 curve and the SHA-256 hash algorithm” (ECDSA z użyciem krzywej P-256 i algorytmu haszującego SHA-256). Za pomocą kryptografii internetowej 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ą publicznego klucza 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 połączone kropkami) jest wysyłany do usługi powiadomień push w internecie jako nagłówek Authorization z dodatkiem 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 bezpieczny dla adresu URL ciąg zakodowany w formacie base64 z dodanym na początku znakiem p256ecdsa=.

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

Szyfrowanie ładunku

Następnie zobaczmy, jak wysłać ładunek z wiadomością push, aby po otrzymaniu wiadomości push przez aplikację internetową mogła ona uzyskać dostęp do otrzymanych danych.

Często pojawia się pytanie, dlaczego w przypadku powiadomień push w internecie ładunek musi być zaszyfrowany. W przypadku aplikacji natywnych wiadomości push mogą wysyłać dane w formie zwykłego tekstu.

Zaletą powiadomień push w internecie jest to, że wszystkie usługi push korzystają z tego samego interfejsu API (protokołu powiadomień push w internecie), więc deweloperzy nie muszą się martwić, kto jest dostawcą usługi push. Możemy wysłać żądanie w odpowiednim formacie i oczekiwać, że zostanie wysłana wiadomość push. Wadą tego rozwiązania jest to, że deweloperzy mogą wysyłać wiadomości do usługi push, która nie jest godna zaufania. Dzięki zaszyfrowaniu ładunku usługa push nie może odczytać wysyłanych danych. Tylko przeglądarka może odszyfrować informacje. Chroni to dane użytkownika.

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

Zanim przejdziemy do konkretnych kroków szyfrowania ładunku wiadomości push, omówimy techniki, które będą używane podczas procesu szyfrowania. (Wielkie podziękowania dla Mata Scalesa za świetny artykuł o szyfrowaniu push).

ECDH i HKDF

Zarówno ECDH, jak i HKDF są używane w procesie szyfrowania i przynoszą korzyści w zakresie szyfrowania informacji.

ECDH: wymiana kluczy Diffiego-Hellmana na krzywej eliptycznej

Załóżmy, że 2 osoby, Alicja i Robert, chcą udostępniać sobie informacje. Zarówno Alicja, jak i Robert mają własne klucze publiczne i prywatne. Alicja i Robert udostępniają sobie nawzajem klucze publiczne.

Przydatną właściwością kluczy wygenerowanych za pomocą ECDH jest to, że Alicja może użyć swojego klucza prywatnego i klucza publicznego Boba, aby utworzyć tajną wartość „X”. Michał 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ę udostępnionym hasłem, a Alicja i Bob muszą tylko udostępnić swój klucz publiczny. Teraz Robert i Alicja mogą używać „X” do szyfrowania i odszyfrowywania wiadomości między sobą.

O ile mi wiadomo, ECDH określa właściwości krzywych, które umożliwiają tę „funkcję” tworzenia udostępnionego hasła „X”.

To ogólne wyjaśnienie działania ECDH. Jeśli chcesz dowiedzieć się więcej, obejrzyj szczegółowy film o ECDH.

W przypadku kodu większość języków i platform ma biblioteki, które ułatwiają generowanie tych kluczy.

W węźle wykonamy te czynności:

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

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

HKDF: funkcja derywacji klucza oparta na HMAC

W Wikipedii znajduje się zwięzły opis HKDF:

HKDF to funkcja derywacji klucza oparta na HMAC, która przekształca każdy słaby materiał klucza w kryptograficznie silny materiał klucza. Może być używany np. do przekształcania udostępnionych kluczy tajnych wymienianych w ramach protokołu Diffie-Hellman w materiał klucza odpowiedni do użycia w szyfrowaniu, sprawdzaniu integralności lub uwierzytelnianiu.

HKDF przyjmuje dane wejściowe, 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 wynikowe klucze HKDF w przypadku powiadomień push w internecie 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);
}

Dziękujemy Matowi Scale za ten przykładowy kod.

Obejmuje to w przybliżeniu ECDHHKDF.

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

Będzie on używany podczas szyfrowania naszego ładunku. Teraz przyjrzyjmy się, jakie dane wejściowe przyjmujemy i jak są one szyfrowane.

Wejścia

Jeśli chcemy wysłać do użytkownika wiadomość push z ładunkiem, potrzebujemy 3 rodzajów danych wejściowych:

  1. sam ładunek;
  2. Obiekt tajny auth z usługi PushSubscription.
  3. Kluczyk p256dh z pojazdu PushSubscription.

Widzieliśmy, że wartości authp256dh są pobierane z PushSubscription, ale 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 należy jej udostępniać poza aplikacją.

Klucz p256dh jest kluczem publicznym, czasami nazywanym kluczem publicznym klienta. W tym artykule będziemy nazywać p256dh kluczem publicznym subskrypcji. Klucz publiczny subskrypcji jest generowany przez przeglądarkę. Przeglądarka zachowa klucz prywatny w tajemnicy i użyje go do odszyfrowania ładunku.

Te 3 wartości, auth, p256dhpayload, są potrzebne jako dane wejściowe, a wynikiem procesu szyfrowania będzie zaszyfrowany ładunek, wartość soli i klucz publiczny używany tylko do szyfrowania danych.

Salt

Ciąg zaburzający musi zawierać 16 bajtów losowych danych. W NodeJS, aby utworzyć sól, wykonujemy te czynności:

const salt = crypto.randomBytes(16);

Klucze publiczne i prywatne

Klucze publiczny i prywatny powinny być wygenerowane przy użyciu krzywej eliptycznej P-256. W Node zrobimy to w ten sposób:

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

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

Będziemy je nazywać „kluczami lokalnymi”. Służą one tylko do szyfrowania i nie mają nic wspólnego z kluczami serwera aplikacji.

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

Udostępniony klucz tajny

Pierwszym krokiem jest utworzenie udostępnionego hasła za pomocą klucza publicznego subskrypcji i naszego nowego klucza prywatnego (pamiętasz wyjaśnienie dotyczące ECDH z Alicją i Bobem? Just like that).

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

Jest on używany w następnym kroku do obliczenia klucza pseudolosowego (PRK).

Pseudolosowy klucz

Pseudolosowy klucz (PRK) to połączenie tajnego klucza autoryzacji subskrypcji push i utworzonego właśnie udostępnionego hasła.

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

Możesz się zastanawiać, do czego służy ciąg Content-Encoding: auth\0. Krótko mówiąc, nie ma jasnego celu, chociaż przeglądarki mogą odszyfrować wiadomość przychodzącą i poszukać oczekiwanego kodowania treści. Znak \0 dodaje na końcu bufora bajt o wartości 0. Jest to oczekiwane przez przeglądarki odszyfrowujące wiadomość, które oczekują tylu bajtów dla kodowania treści, a następnie bajtu o wartości 0 i zaszyfrowanych danych.

Nasz pseudolosowy klucz to po prostu uruchomienie uwierzytelniania, udostępnionego hasła i informacji o kodowaniu za pomocą funkcji HKDF (czyli zwiększenie jego siły kryptograficznej).

Kontekst

„Kontekst” to zestaw bajtów, który jest używany do obliczania 2 wartości w późniejszym etapie szyfrowania w przeglądarce. Jest to tablica bajtów zawierająca klucz publiczny subskrypcji i lokalny klucz publiczny.

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órej następuje sam klucz, a potem liczba bajtów w lokalnym kluczu publicznym, po której następuje sam klucz.

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

Klucz szyfrowania treści i wartość nonce

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

Klucz szyfrujący treść (CEK) to klucz, który będzie ostatecznie używany do szyfrowania ładunku.

Najpierw musimy utworzyć bajty danych dla wartości nonce i CEK, czyli po prostu ciąg kodowania treści, a następnie bufor kontekstu, który właśnie obliczyliśmy:

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óra łączy sól i PRK z 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 uzyskujemy klucz nonce i klucz szyfrowania treści.

Przeprowadź szyfrowanie

Gdy mamy już klucz szyfrowania treści, możemy zaszyfrować ładunek.

Tworzymy szyfr AES128, używając klucza szyfrowania treści jako klucza, a wartości 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 dopełnienia chcemy dodać na jego początku. Dodanie dopełnienia zmniejsza ryzyko, że osoby podsłuchujące będą mogły określić „rodzaje” wiadomości na podstawie rozmiaru ładunku.

Musisz dodać 2 bajty dopełnienia, aby wskazać długość dodatkowego dopełnienia.

Jeśli na przykład nie dodasz dopełnienia, po tych 2 bajtach będziesz odczytywać ładunek. Jeśli dodasz 5 bajtów dopełnienia, pierwsze 2 bajty będą miały wartość 5, więc odbiorca odczyta dodatkowe 5 bajtów, a potem zacznie odczytywać ładunek.

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

Następnie przepuszczamy dopełnienie i ładunek przez ten szyfr.

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ć, w jaki sposób ten ładunek jest wysyłany do usługi push.

Nagłówki i treść zaszyfrowanego pakietu

Aby wysłać ten zaszyfrowany ładunek 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żywaną do szyfrowania ładunku.

16-bajtowy sól powinien być zakodowany w formacie base64 bezpiecznym dla adresów URL i dodany do nagłówka Encryption w ten sposób:

Encryption: salt=[URL Safe Base64 Encoded Salt]

Nagłówek Crypto-Key

Widzimy, ż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 używanego do szyfrowania ładunku.

Wynikowy 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ą stałe wartości. Jest to pokazane poniżej.

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 pole Content-Type jest ustawione na application/octet-stream. Wynika to z faktu, że zaszyfrowany ładunek musi być wysyłany jako strumień bajtów.

W NodeJS zrobisz 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 serwera aplikacji i tokenów JWT (czyli sposób identyfikowania aplikacji w usłudze push) oraz nagłówki używane do wysyłania zaszyfrowanego ładunku.

Usługi push używają dodatkowych nagłówków, aby zmieniać zachowanie wysyłanych wiadomości. Niektóre z tych nagłówków są wymagane, a inne opcjonalne.

Nagłówek TTL

Wymagany

TTL (lub czas życia danych (TTL)) to liczba całkowita określająca liczbę sekund, przez które wiadomość push ma być przechowywana 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 na zero, usługa push spróbuje natychmiast dostarczyć wiadomość, ale jeśli urządzenie będzie niedostępne, wiadomość zostanie natychmiast usunięta z kolejki usługi push.

Technicznie usługa push może zmniejszyć TTL wiadomości push, jeśli tego chce. Możesz to sprawdzić, analizując nagłówek TTL w odpowiedzi z usługi push.

Temat

Opcjonalny

Tematy to ciągi znaków, których można użyć 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 podczas gdy urządzenie jest offline, wysyłanych jest wiele wiadomości, a użytkownik ma zobaczyć tylko najnowszą z nich po włączeniu urządzenia.

Pilność

Opcjonalny

Priorytet informuje usługę push, jak ważna jest wiadomość dla użytkownika. Może to być używane przez usługę push do oszczędzania baterii urządzenia użytkownika poprzez wybudzanie go tylko w przypadku ważnych wiadomości, gdy poziom baterii jest niski.

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

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

Wszystko w jednym miejscu

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

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

Co więc robimy z odpowiedzią na to żądanie POST?

Odpowiedź z usługi push

Po wysłaniu żądania do usługi push musisz sprawdzić kod stanu odpowiedzi, ponieważ informuje on, czy żądanie zostało zrealizowane.

Kod stanu Opis
201 Utworzono. Prośba o wysłanie wiadomości push została odebrana i zaakceptowana.
429 Zbyt wiele żądań. Oznacza to, że serwer aplikacji osiągnął limit liczby żądań w usłudze push. Usługa push powinna zawierać nagłówek „Retry-After”, aby wskazać, jak długo trzeba czekać, zanim będzie można wysłać kolejną prośbę.
400 Nieprawidłowe żądanie. Zwykle oznacza to, że jeden z nagłówków jest nieprawidłowy lub nieprawidłowo sformatowany.
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 poczekać, aż klient ponownie zasubskrybuje użytkownika.
410 Usunięto. Subskrypcja jest już nieważna i należy ją usunąć z serwera aplikacji. Możesz to odtworzyć, wywołując funkcję `unsubscribe()` w obiekcie `PushSubscription`.
413 Ładunek jest za duży. Minimalny rozmiar ładunku, który musi obsługiwać usługa push, to 4096 bajtów (czyli 4 KB).

Więcej informacji o kodach stanu HTTP znajdziesz w standardzie Web Push (RFC8030).

Co dalej

Code labs