Protokół Web Push Protocol

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

Wysyłają żądania sieciowe, upewniając się, że mają one prawidłowy format. Specyfikacja, która definiuje to żądanie sieciowe, to protokół Web Push.

Diagram przedstawiający wysyłanie wiadomości push z serwera do usługi 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 informacje.

To nie jest najprzyjemniejsza strona powiadomień push w internecie, a ja nie jestem ekspertem od szyfrowania, ale przyjrzyjmy się każdemu elementowi, ponieważ warto wiedzieć, co te biblioteki robią w tle.

Klucze serwera aplikacji

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

Gdy wywołujemy wiadomość push, wysyłamy zestaw nagłówków, które umożliwiają usłudze push uwierzytelnienie aplikacji. (jest to określone w specyfikacji VAPID).

Co to tak naprawdę oznacza i co dokładnie się dzieje? Oto kroki, które należy wykonać, aby uwierzytelnić serwer aplikacji:

  1. Serwer aplikacji podpisuje niektóre informacje 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 zapisanego klucza publicznego otrzymanego z pushManager.subscribe(), aby sprawdzić, czy otrzymane informacje są podpisane kluczem prywatnym powiązanym z kluczem publicznym. Pamiętaj: klucz publiczny to 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 takiego przepływu informacji. (Zwróć uwagę na legendę w lewym dolnym rogu, która wskazuje klucze publiczne i prywatne).

Ilustracja pokazująca, jak klucz prywatny 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 (lub w skrócie JWT) to sposób wysyłania wiadomości do innej firmy, dzięki któremu odbiorca może sprawdzić, kto ją wysłał.

Gdy osoba trzecia otrzyma wiadomość, musi uzyskać 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, więc musi pochodzić od oczekiwanego nadawcy.

Na stronie jwt.io/ znajdziesz wiele bibliotek, które mogą wykonać podpisywanie za Ciebie. Zalecamy korzystanie z nich, gdy tylko jest to możliwe. Dla kompletności 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, który można traktować jako 3 ciągi znaków połączone kropkami.

Ilustracja przedstawiająca ciągi znaków w tokenie internetowym JSON.

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

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

Informacje JWT dotyczące powiadomień push w internecie muszą zawierać te dane:

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

Drugi ciąg znaków to dane JWT. Zawiera on informacje o nadawcy tokena JWT, o tym, dla kogo jest on przeznaczony i jak długo jest ważny.

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

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

Wartość aud to „odbiorcy”, czyli osoby, dla których przeznaczony jest token 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 ważności tokena JWT. Zapobiega to ponownemu użyciu tokena JWT przez osoby, które go przechwycą. Data ważności to sygnatura czasowa w sekundach, która nie może przekraczać 24 godzin.

W Node.js datę ważności ustawia się 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.

Wartość sub musi być adresem URL lub adresem e-mail mailto. Dzięki temu, jeśli usługa push musi skontaktować się z nadawcą, może znaleźć informacje kontaktowe w tokenie JWT. (Dlatego biblioteka web-push potrzebowała adresu e-mail).

Podobnie jak informacje JWT, dane JWT są kodowane jako ciąg base64 bezpieczny dla adresów URL.

Trzeci ciąg znaków, czyli podpis, jest wynikiem połączenia pierwszych 2 ciągów znaków (informacji i danych JWT) kropką, co nazywamy „niepodpisanym tokenem”, i podpisania go.

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ą Web Crypto 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, używając klucza publicznego serwera aplikacji do odszyfrowania podpisu i upewnienia 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 poprzedzającym go ciągiem WebPush, na przykład:

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

Protokół Web Push określa również, że klucz publiczny serwera aplikacji musi być wysyłany w nagłówku Crypto-Key jako ciąg znaków zakodowany w standardzie base64 i bezpieczny dla adresów URL, z poprzedzającym go ciągiem p256ecdsa=.

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

Szyfrowanie ładunku

Teraz zobaczmy, jak możemy wysłać ładunek z wiadomością push, aby po otrzymaniu wiadomości push aplikacja internetowa mogła uzyskać dostęp do otrzymanych danych.

Osoby, które korzystały z innych usług push, często pytają, dlaczego ładunek powiadomienia push w internecie musi być zaszyfrowany. W przypadku aplikacji natywnych wiadomości push mogą wysyłać dane jako zwykły tekst.

Jedną z zalet powiadomień push w internecie jest to, że wszystkie usługi push korzystają z tego samego interfejsu API (protokołu push w internecie), więc deweloperzy nie muszą się martwić, jaka to usługa. Możemy wysłać żądanie w odpowiednim formacie i oczekiwać, że wiadomość push zostanie wysłana. 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 szyfrowaniu ładunku usługa push nie może odczytać wysyłanych danych. Tylko przeglądarka może odszyfrować te informacje. Ma to na celu ochronę danych użytkownika.

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

Zanim omówimy konkretne kroki szyfrowania ładunku wiadomości push, powinniśmy omówić niektóre techniki, które będą używane podczas procesu szyfrowania. (Wielkie podziękowania dla Mata Scalesa za jego doskonały artykuł o szyfrowaniu powiadomień push).

ECDH i HKDF

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

ECDH: wymiana kluczy Diffiego-Hellmana oparta na krzywej eliptycznej

Wyobraźmy sobie, że Alicja i Robert chcą wymienić się informacjami. Alicja i Robert mają własne klucze publiczne i prywatne. Alicja i Robert udostępniają sobie nawzajem klucze publiczne.

Przydatną właściwością kluczy generowanych za pomocą ECDH jest to, że Alicja może użyć swojego klucza prywatnego i klucza publicznego Boba, aby utworzyć tajną wartość „X”. Bob 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” jest wspólnym sekretem, a Alicja i Bob musieli udostępnić tylko swój klucz publiczny. Teraz Robert i Alicja mogą używać klucza „X” do szyfrowania i odszyfrowywania wiadomości, które sobie przesyłają.

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

To ogólne wyjaśnienie ECDH. Jeśli chcesz dowiedzieć się więcej, obejrzyj film z bardziej szczegółowym omówieniem ECDH.

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

W Node.js wykonujemy 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

Wikipedia zawiera zwięzły opis HKDF:

HKDF to funkcja derywacji klucza oparta na HMAC, która przekształca dowolny słaby materiał klucza w materiał klucza o silnym szyfrowaniu. Można jej użyć na przykład do przekonwertowania udostępnionych obiektów tajnych wymienianych przez Diffie-Hellmana na materiał klucza odpowiedni do szyfrowania, sprawdzania integralności lub uwierzytelniania.

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

Specyfikacja definiująca to szyfrowanie wymaga użycia SHA-256 jako algorytmu szyfrowania, a wynikowe klucze HKDF w powiadomieniach push w internecie nie powinny być dłuższe niż 256 bitów (32 bajty).

W Node 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 Mata Scale'a.

Obejmuje to w przybliżeniu ECDH i HKDF.

ECDH to bezpieczny sposób udostępniania kluczy publicznych i generowania udostępnionego tajnego klucza. HKDF to sposób na zabezpieczenie niebezpiecznych materiałów.

Będzie on używany podczas szyfrowania ładunku. Teraz przyjrzyjmy się danym wejściowym i sposobowi ich szyfrowania.

Wejścia

Gdy chcemy wysłać użytkownikowi wiadomość push z ładunkiem, potrzebujemy 3 danych wejściowych:

  1. sam ładunek;
  2. Obiekt tajny auth z PushSubscription.
  3. Klucz p256dh z PushSubscription.

Widzieliśmy, że wartości auth i p256dh są pobierane z PushSubscription, ale przypomnijmy, ż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 aplikacją.

Klucz p256dh jest kluczem publicznym, który czasami jest nazywany kluczem publicznym klienta. W tym miejscu 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, p256dh i payload) są potrzebne jako dane wejściowe, a wynikiem procesu szyfrowania będą zaszyfrowane dane, wartość ciągu zaburzającego 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 publiczne i prywatne powinny być generowane przy użyciu krzywej eliptycznej P-256, co w Node można zrobić w ten sposób:

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

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

Te klucze będziemy nazywać „kluczami lokalnymi”. Są one używane tylko do szyfrowania i nie mają nic wspólnego z kluczami serwera aplikacji.

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

Udostępniony klucz tajny

Pierwszym krokiem jest utworzenie wspólnego obiektu tajnego przy użyciu klucza publicznego subskrypcji i naszego nowego klucza prywatnego (pamiętasz wyjaśnienie 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

Klucz pseudolosowy (PRK) to połączenie tajnego klucza uwierzytelniania subskrypcji push i utworzonego przez nas wspólnego klucza tajnego.

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 on jasnego celu, chociaż przeglądarki mogą odszyfrować wiadomość przychodzącą i poszukać oczekiwanego kodowania treści. \0 dodaje bajt o wartości 0 na końcu bufora. Jest to oczekiwane przez przeglądarki odszyfrowujące wiadomość, które będą oczekiwać określonej liczby bajtów kodowania treści, po których następuje bajt o wartości 0, a następnie zaszyfrowane dane.

Nasz klucz pseudolosowy po prostu uruchamia uwierzytelnianie, wspólny klucz tajny i część informacji o kodowaniu przez HKDF (czyli wzmacnia go kryptograficznie).

Kontekst

„Kontekst” to zestaw bajtów, który służy do obliczania 2 wartości później w przeglądarce szyfrowania. Jest to zasadniczo 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,
]);

Ostateczny bufor kontekstu to etykieta, liczba bajtów w kluczu publicznym subskrypcji, a następnie sam klucz, liczba bajtów lokalnego klucza publicznego i sam klucz.

Dzięki tej wartości kontekstu możemy utworzyć liczbę jednorazową i klucz szyfrowania treści (CEK).

Klucz szyfrowania treści i liczba jednorazowa

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

Klucz szyfrowania treści (CEK) to klucz, który zostanie ostatecznie użyty do zaszyfrowania ładunku.

Najpierw musimy utworzyć bajty danych dla liczby jednorazowej i klucza CEK, który jest po prostu ciągiem 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 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);

W ten sposób uzyskujemy liczbę jednorazową 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 liczba jednorazowa jest wektorem inicjującym.

W Node robi się to tak:

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

Zanim zaszyfrujemy ładunek, musimy określić, ile dopełnienia chcemy dodać na początku ładunku. Powodem, dla którego chcemy dodać dopełnienie, jest to, że zapobiega ono ryzyku, że podsłuchujący będą mogli określić „typy” 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, otrzymasz 2 bajty o wartości 0, czyli bez dopełnienia. Po tych 2 bajtach odczytasz ładunek. Jeśli dodasz 5 bajtów dopełnienia, pierwsze 2 bajty będą miały wartość 5, więc konsument odczyta dodatkowe 5 bajtów, a następnie 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ć, jak ten ładunek jest wysyłany do usługi push.

Zaszyfrowane nagłówki i treść ładunku

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

Nagłówek szyfrowania

Nagłówek „Encryption” musi zawierać ciąg zaburzający użyty do zaszyfrowania ładunku.

16-bajtowy ciąg zaburzający powinien być zakodowany w formacie base64 URL i dodany do nagłówka szyfrowania w ten sposób:

Encryption: salt=[URL Safe Base64 Encoded Salt]

Nagłówek Crypto-Key

W sekcji „Klucze serwera aplikacji” nagłówek Crypto-Key jest używany do przechowywania klucza publicznego 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, długości i kodowania treści

Nagłówek Content-Length to liczba bajtów w zaszyfrowanych danych. Nagłówki „Content-Type” i „Content-Encoding” mają stałe wartości. Zostało to przedstawione 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 ma wartość application/octet-stream. Jest to konieczne, ponieważ zaszyfrowany ładunek musi być wysyłany jako strumień bajtów.

W NodeJS można to zrobić w ten sposób:

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 JWT i kluczy serwera aplikacji (czyli jak zidentyfikować aplikację za pomocą usługi push) oraz nagłówki używane do wysyłania zaszyfrowanego ładunku.

Istnieją dodatkowe nagłówki, których usługi push używają do zmiany zachowania 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 które wiadomość push ma być przechowywana w usłudze push przed dostarczeniem. Gdy upłynie czas TTL, 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 0, usługa push spróbuje dostarczyć wiadomość natychmiast, ale jeśli urządzenie będzie nieosiągalne, wiadomość zostanie natychmiast usunięta z kolejki usługi push.

Technicznie rzecz biorąc, usługa push może w razie potrzeby zmniejszyć wartość TTL wiadomości push. 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ą pasujące nazwy tematów.

Jest to przydatne w sytuacjach, gdy urządzenie jest offline i wysyłanych jest wiele wiadomości, a użytkownik powinien zobaczyć tylko ostatnią wiadomość po włączeniu urządzenia.

Pilność

Opcjonalny

Pilność wskazuje usłudze push, jak ważna jest wiadomość dla użytkownika. Usługa push może używać tej wartości, aby oszczędzać baterię urządzenia użytkownika, wybudzając je 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 razem

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

Gdy masz już zaszyfrowane dane i powyższe nagłówki, musisz tylko wysłać żądanie POST do endpoint w 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, który poinformuje Cię, czy żądanie zostało zrealizowane.

Kod stanu Opis
201 Utworzono. Żądanie wysłania wiadomości push zostało odebrane i zaakceptowane.
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”, który wskazuje, po jakim czasie można wysłać kolejne żądanie.
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ąć `PushSubscription` i poczekać, aż klient ponownie zasubskrybuje użytkownika.
410 Usunięto. Subskrypcja nie jest już ważna i należy ją usunąć z serwera aplikacji. Można to odtworzyć, wywołując funkcję `unsubscribe()` w obiekcie `PushSubscription`.
413 Rozmiar ładunku 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 też w standardzie Web Push (RFC8030).

Co dalej

Ćwiczenia w Codelabs