Pobierz API z Cookie

201

Wypróbowuję nowy interfejs API pobierania, ale mam problem z plikami cookie. W szczególności, po udanym zalogowaniu się, w przyszłych żądaniach pojawia się nagłówek Cookie, ale Fetch wydaje się ignorować te nagłówki, a wszystkie moje żądania złożone za pomocą Fetch są nieautoryzowane.

Czy to dlatego, że pobieranie nie jest jeszcze gotowe lub pobieranie nie działa z plikami cookie?

Buduję swoją aplikację za pomocą pakietu Webpack. Używam również Fetch w React Native, który nie ma tego samego problemu.

Khanetor
źródło

Odpowiedzi:

280

Funkcja pobierania nie korzysta domyślnie z plików cookie. Aby włączyć obsługę plików cookie, wykonaj następujące czynności:

fetch(url, {
  credentials: "same-origin"
}).then(...).catch(...);
Khanetor
źródło
55
to samo pochodzenie już nie działa, włącza (patrz odpowiedź @ Jerry'ego): developers.google.com/web/updates/2015/03/introduction-to-fetch
jpic
7
@jpic: „dołącz” działa tylko w przypadku żądań pochodzących z różnych źródeł, ale nie dotyczy żądań tego samego pochodzenia. Oficjalne dokumenty: github.com/github/fetch#sending-cookies
HoldOffHunger
Jaki jest zatem powód posiadania plików cookie httponly, jeśli można je odczytać w js z funkcją pobierania?
Martin Bajcar,
4
Wierzę, same-origin(który ma jeszcze pracę) oznacza, że więcej nagłówki będą przestrzegane (cookies, etc), ale kod będzie mieć ograniczony dostęp do odpowiedzi.
Coderer
2
@JohnBalvinAriasThx. Jak później zrozumiałem, posiadanie pliku cookie httponly oznacza, że ​​nie można go odczytać document.cookie, ale nadal jest dostępny dla żądań ajax lub pobierania.
Martin Bajcar
185

Oprócz odpowiedzi @ Khanetor, dla tych, którzy pracują z wnioskami z różnych źródeł: credentials: 'include'

Przykładowe żądanie pobierania JSON:

fetch(url, {
  method: 'GET',
  credentials: 'include'
})
  .then((response) => response.json())
  .then((json) => {
    console.log('Gotcha');
  }).catch((err) => {
    console.log(err);
});

https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials

zurfyx
źródło
9
jak ustawić ciasteczko?
pomo
2
Plik cookie jest ustawiany po stronie serwera. W moim przypadku korzystałem z plików cookie httponly.
Khanetor,
3
@Khanetor czy mogę ustawić pliki cookie za pomocą document.cookie przez javascript, a następnie wysłać zapytanie?
ospider
@ospider Możesz wysłać go w nagłówku.
10101010,
2
@ospider Stwierdziłem, że samo ustawienie wartości document.cookiewystarczyło, aby uwzględnić ją w żądaniach.
skwidbreth,
36

Właśnie rozwiązałem. Tylko dwa f. dni brutalnej siły

Dla mnie sekret był następujący:

  1. Zadzwoniłem do POST / api / auth i przekonałem się, że pliki cookie zostały pomyślnie odebrane.

  2. Następnie wywołując GET / api / users / credentials: 'include'i otrzymałem 401 nieautoryzowanych informacji, ponieważ z prośbą nie wysłano żadnych plików cookie.

Klawisz należy ustawić również credentials: 'include'dla pierwszego /api/authpołączenia.

użytkownik1671599
źródło
1
Mam dokładnie twój problem. Sesyjny plik cookie nigdy nie jest wysyłany na żądanie danych GET. więc 401. Próbowałem Axios i Fetch. ten sam wynik. 2 możliwości: POST logowania nie przechowuje otrzymanego pliku cookie lub następujące dane GET nie wysyłają zapisanego pliku cookie
Rhubarb65,
@ Rhubarb65, aby wygrać, należy określić credentials: 'include'jako pierwszyPOST /api/auth
użytkownik1671599
Tak, miałem to, ale chcę dość. Korzystam z serwera proxy devserver (klient HTTP)
Rhubarb65,
Tak, miałem dane uwierzytelniające, ale to nie wystarczyło. Używałem serwera proxy devserver, aby ominąć CORS: (klient http) - proxy - (serwer https). Uważam, że oznaczało to, że sesyjny plik cookie z serwera nie został ustawiony w przeglądarce, ponieważ bezpieczne pliki cookie wymagają protokołu https. Dodałem więc flagę https: true w serwerze proxy devserver i to naprawiło
Rhubarb65,
1
Cóż, na zdrowie. Twoja odpowiedź oznaczała, że ​​zajęło mi to tylko 1 dzień brutalnej siły. :)
Michael
16

Jeśli czytasz to w 2019 roku, credentials: "same-origin"jest wartością domyślną.

fetch(url).then
alextrastero
źródło
1
Pamiętaj jednak, że nie wszyscy korzystają z odpowiednio zaktualizowanej przeglądarki. Natknąłem się na to pytanie, ponieważ moja własna wersja przeglądarki Firefox (60.x, najnowsza wersja Debian Stretch) nie ustawia jej domyślnie.
philh
2

Dodam tylko prawidłowe odpowiedzi tutaj dla .net webapi2użytkowników.

Jeśli używasz, corsponieważ witryna klienta jest obsługiwana z innego adresu niż twój webapi, musisz również uwzględnić SupportsCredentials=truekonfigurację po stronie serwera.

        // Access-Control-Allow-Origin
        // https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api
        var cors = new EnableCorsAttribute(Settings.CORSSites,"*", "*");
        cors.SupportsCredentials = true;
        config.EnableCors(cors);
Mark Dornian
źródło
0

To działa dla mnie:

import Cookies from 'universal-cookie';
const cookies = new Cookies();

function headers(set_cookie=false) {
  let headers = {
    'Accept':       'application/json',
    'Content-Type': 'application/json',
    'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
};
if (set_cookie) {
    headers['Authorization'] = "Bearer " + cookies.get('remember_user_token');
}
return headers;
}

Następnie zbuduj połączenie:

export function fetchTests(user_id) {
  return function (dispatch) {
   let data = {
    method:      'POST',
    credentials: 'same-origin',
    mode:        'same-origin',
    body:        JSON.stringify({
                     user_id: user_id
                }),
    headers:     headers(true)
   };
   return fetch('/api/v1/tests/listing/', data)
      .then(response => response.json())
      .then(json => dispatch(receiveTests(json)));
    };
  }
aarkerio
źródło