Dostęp asynchroniczny do plików cookie HTTP

Victor Costan

Czym jest interfejs Cookie Store API?

Interfejs Cookie Store API udostępnia pliki cookie HTTP mechanizmom Service Worker i oferuje asynchroniczną alternatywę dla document.cookie. Interfejs API ułatwia:

  • Unikaj zacięć w wątku głównym, uzyskując dostęp do plików cookie asynchronicznie.
  • Unikaj sprawdzania plików cookie, ponieważ zmiany w plikach cookie mogą być widoczne.
  • Dostęp do plików cookie z serwisów worker.

Przeczytaj wyjaśnienie

Obecny stan,

Krok Stan
1. Tworzenie wyjaśnienia Zakończono
2. Tworzenie wstępnej wersji specyfikacji Zakończono
**3. Zbieranie opinii i ulepszanie specyfikacji** **W toku**
4. Wersja próbna origin Wstrzymana
5. Uruchom Nie rozpoczęto

Jak korzystać z asynchronicznego magazynu plików cookie?

Włącz okres próbny punktu początkowego

Aby przetestować ten interfejs lokalnie, włącz interfejs API w wierszu poleceń:

chrome --enable-blink-features=CookieStore

Podanie tej opcji w wierszu poleceń powoduje globalne włączenie interfejsu API w Chrome w bieżącej sesji.

Możesz też włączyć flagę #enable-experimental-web-platform-features w pliku chrome://flags.

(Prawdopodobnie) nie potrzebujesz plików cookie

Zanim przejdziemy do nowego interfejsu API, warto pamiętać, że pliki cookie są nadal najgorszym sposobem przechowywania danych po stronie klienta w ramach platformy internetowej i należy używać ich tylko w razie potrzeby. Nie jest to przypadek. Pliki cookie były pierwszym mechanizmem przechowywania po stronie klienta w internecie i od tego czasu dużo się nauczyliśmy.

Oto główne powody, dla których należy unikać plików cookie:

  • Pliki cookie przekazują schemat magazynowania do interfejsu API na zapleczu. Każde żądanie HTTP zawiera zrzut dysku z plikami cookie. Dzięki temu inżynierowie pracujący nad backendem mogą łatwo wprowadzać zależności od bieżącego formatu plików cookie. Gdy to nastąpi, front-end nie będzie mógł zmienić schematu magazynu bez wdrożenia odpowiedniej zmiany w back-endzie.

  • Pliki cookie mają złożony model zabezpieczeń. Funkcje nowoczesnej platformy internetowej są zgodne z zasadami dotyczącymi tego samego źródła, co oznacza, że każda aplikacja ma własny piaskownicy i jest całkowicie niezależna od innych aplikacji, które użytkownik może uruchamiać. Zakresy działania plików cookie to znacznie bardziej skomplikowana kwestia bezpieczeństwa, a samo podsumowanie tej kwestii spowodowałoby dwukrotne zwiększenie rozmiaru tego artykułu.

  • Pliki cookie mają wysoki koszt wydajności. W każdym żądaniu HTTP przeglądarki muszą zawierać migawkę plików cookie, więc każda zmiana plików cookie musi być propagowana w warstwach pamięci i sieci. Nowoczesne przeglądarki mają bardzo zoptymalizowane implementacje pamięci cookie, ale nigdy nie będziemy w stanie stworzyć plików cookie tak wydajnych jak inne mechanizmy przechowywania, które nie muszą komunikować się ze stekiem sieciowym.

Z wszystkich powyższych powodów nowoczesne aplikacje internetowe nie powinny używać plików cookie, a zamiast tego powinny przechowywać identyfikator sesji w interfejsie IndexedDB i dodawać go jawnie do nagłówka lub treści określonych żądań HTTP za pomocą interfejsu fetch API.

Mimo to czytasz ten artykuł, ponieważ masz dobry powód, aby używać plików cookie.

Stary interfejs API document.cookie jest prawie zawsze źródłem problemów z płynnością w aplikacji. Na przykład za każdym razem, gdy używasz gettera document.cookie, przeglądarka musi zatrzymać wykonywanie kodu JavaScriptu, dopóki nie otrzyma żądanych informacji o plikach cookie. Może to wymagać przejścia do innego procesu lub odczytu z dysku, co spowoduje opóźnienia w interfejsie.

Prostym rozwiązaniem tego problemu jest przejście z gettera document.cookie na asynchroniczny interfejs Cookie Store API.

await cookieStore.get('session_id');

// {
//   domain: "example.com",
//   expires: 1593745721000,
//   name: "session_id",
//   path: "/",
//   sameSite: "unrestricted",
//   secure: true,
//   value: "yxlgco2xtqb.ly25tv3tkb8"
// }

Setter document.cookie można zastąpić w podobny sposób. Pamiętaj, że zmiana zostanie zastosowana dopiero po zakończeniu obietnicy zwracanej przez funkcjęcookieStore.set.

await cookieStore.set({name: 'opt_out', value: '1'});

// undefined

Obserwuj, nie sonduj

Popularnym sposobem uzyskiwania dostępu do plików cookie z JavaScriptu jest wykrywanie, kiedy użytkownik się wyloguje, i aktualizowanie interfejsu użytkownika. Obecnie jest to realizowane przez odczyt zapytańdocument.cookie, co powoduje opóźnienia i ma negatywny wpływ na żywotność baterii.

Interfejs Cookie Store API zapewnia alternatywną metodę obserwowania zmian plików cookie, która nie wymaga sprawdzania.

cookieStore.addEventListener('change', event => {
  for (const cookie of event.changed) {
    if (cookie.name === 'session_id') sessionCookieChanged(cookie.value);
  }
  for (const cookie of event.deleted) {
    if (cookie.name === 'session_id') sessionCookieChanged(null);
  }
});

Skrypty usługi powitalnej

Ze względu na konstrukcję synchroniczną interfejs API document.cookie nie został udostępniony składnikom service worker. Interfejs Cookie Store API jest asynchroniczny, dlatego jest dozwolony w serwisach workers.

Interakcja z plikami cookie przebiega tak samo w kontekście dokumentów i w mechanizmach roboczych usługi.

// Works in documents and service workers.
async function logOut() {
  await cookieStore.delete('session_id');
}

Obserwowanie zmian plików cookie jest jednak w przypadku usług działających w tle nieco inne. Wybudzenie skryptu service worker może być dość kosztowne, dlatego musimy w sposób jawny opisać zmiany w plikach cookie, którymi się on interesuje.

W przykładzie poniżej aplikacja, która używa IndexedDB do buforowania danych użytkownika, monitoruje zmiany w pliku cookie sesji i usuwanie danych z bufora po wylogowaniu użytkownika.

// Specify the cookie changes we're interested in during the install event.
self.addEventListener('install', event => {
  event.waitUntil(cookieStore.subscribeToChanges([{name: 'session_id'}]));
});

// Delete cached data when the user logs out.
self.addEventListener('cookiechange', event => {
  for (const cookie of event.deleted) {
    if (cookie.name === 'session_id') {
      indexedDB.deleteDatabase('user_cache');
      break;
    }
  }
});

Sprawdzone metody

Już wkrótce.

Prześlij opinię

Jeśli zdecydujesz się wypróbować ten interfejs API, daj nam znać, co o nim myślisz. Prześlij informacje o kształcie interfejsu API do repozytorium specyfikacji i zgłoś błędy w implementacji do komponentu Blink>Storage>CookiesAPI Blink.

Jesteśmy szczególnie zainteresowani pomiarami skuteczności i przypadkami użycia innymi niż te opisane w tym objaśnieniu.

Dodatkowe materiały