Spraw, aby Axios automatycznie wysyłało pliki cookie w swoich żądaniach

121

Wysyłam żądania od klienta do mojego serwera Express.js za pomocą Axios.

Ustawiam plik cookie na kliencie i chcę odczytać ten plik cookie ze wszystkich żądań Axios bez ręcznego dodawania ich do żądania ręcznego.

Oto przykład żądania od strony mojego klienta:

axios.get(`some api url`).then(response => ...

Próbowałem uzyskać dostęp do nagłówków lub plików cookie, korzystając z następujących właściwości na moim serwerze Express.js:

req.headers
req.cookies

Żaden z nich nie zawierał żadnych plików cookie. Używam oprogramowania pośredniczącego parsera plików cookie:

app.use(cookieParser())

Jak sprawić, by Axios automatycznie wysyłało pliki cookie w żądaniach?

Edytować:

Ustawiłem plik cookie na kliencie w ten sposób:

import cookieClient from 'react-cookie'

...
let cookie = cookieClient.load('cookie-name')
if(cookie === undefined){
      axios.get('path/to/my/cookie/api').then(response => {
        if(response.status == 200){
          cookieClient.save('cookie-name', response.data, {path:'/'})
        }
      })
    }
...

Chociaż używa również Axios, nie ma znaczenia dla pytania. Chcę po prostu osadzić pliki cookie we wszystkich moich żądaniach po ustawieniu pliku cookie.

Kunok
źródło
1
jak ustawiłeś plik cookie na kliencie? pokaż przykładowy kod :)
Tzook Bar Noy
@TzookBarNoy Dodano kod w pytaniu
Kunok
Pliki cookie są ustawiane przez serwery z Set-Cookie, a nie przez klienta, myślę, że masz na myśli czytanie pliku cookie na kliencie. Zgodnie z protokołem Cookie, klient powinien umieszczać nagłówek Cookie w swoich żądaniach wysyłanych do serwera wystawiającego ciasteczka.
Hans Poo
Spójrz na ten stackoverflow.com/questions/53898031/…
Ender Bonnet

Odpowiedzi:

242

Miałem ten sam problem i naprawiłem go, korzystając z withCredentialswłaściwości.

XMLHttpRequest z innej domeny nie może ustawić wartości plików cookie dla własnej domeny, chyba że właściwość withCredentials ma wartość true przed wykonaniem żądania.

axios.get('some api url', {withCredentials: true});
fingerpich
źródło
8
Jeśli próbujesz połączyć się z aplikacją Express - musisz użyć cors i użyć tych ustawień. Wymagane jest pochodzenie żądania. app.use (cors ({credentials: true, origin: ' localhost: 8080 '}));
DogCoffee
17
zauważ, że zadziała to tylko wtedy, gdy Access-Control-Allow-Originnagłówek w odpowiedzi nie jest ustawiony na symbol wieloznaczny (*)
Jerry Zhang
1
@JerryZhang Co masz na myśli? Mam ten sam problem, jeśli Access-Control-Allow-Originnie jest ustawiony na *to, oznacza to, że nie
wyślę
5
Odpowiedź wymaga ustawienia Access-Control-Allow-Originwartości domeny, z której chcesz wysłać żądanie XHR. np. https://a.comjest serwerem, https://b.comjest klientem i https://b.comjest ładowany do czyjejś przeglądarki i używa go XMLHTTPRequestdo wysyłania żądań https://a.com. Dodatkowo, aby ustawić XMLHTTPRequest(zainicjowane w https://a.com) withCredential: true, serwer - https://b.comrównież musi być skonfigurowany, aby nagłówek odpowiedzi zawierałAccess-Control-Allow-Origin: https://a.com
Jerry Zhang
Mam z tym mały problem ... jeśli mam jako serwer b jako klienta (tj. Stronę reagowania), to jeśli ustawię to na true, to wyśle ​​poświadczenia a, a nie poświadczenia b ... LOL. .. OK, to nie jest zabawne.
golddragon007
24

TL; DR:

{ withCredentials: true } lub axios.defaults.withCredentials = true


Z dokumentacji Axios

withCredentials: false, // default

withCredentials wskazuje, czy żądania kontroli dostępu między lokacjami powinny być wykonywane przy użyciu poświadczeń

Jeśli spełniasz { withCredentials: true }swoją prośbę, powinno działać.

Lepszym sposobem byłoby ustawienie withCredentialsjak truewaxios.defaults

axios.defaults.withCredentials = true

Fatih Acet
źródło
5
Wysyłanie danych logowania przy każdym żądaniu to zła praktyka. Te kontrole są na miejscu z jakiegoś powodu. Rozmowa z inną usługą, wysyłanie wszystkich plików cookie - niezależnie od tego, czy są używane, jest dojrzała do wykorzystania.
colm.anseo
2
@colminator będą wysyłane tylko pliki cookie, które mają domenę serwera jako domenę. (Domyślnie nie będą one również wysyłane do żadnych subdomen i może być dalej filtrowane na podstawie ścieżki). W efekcie wysyłamy tylko pliki cookie serwera, które zostały ustawione przez serwer.
M3RS
15

Nie jestem zaznajomiony z Axios, ale o ile wiem, w javascript i ajax jest opcja

withCredentials: true

Spowoduje to automatyczne wysłanie pliku cookie po stronie klienta. Na przykład ten scenariusz jest również generowany za pomocą paszportjs, które ustawiają plik cookie na serwerze

RITESH ARORA
źródło
11

Ważne jest również ustawienie niezbędnych nagłówków w odpowiedzi ekspresowej. Oto te, które pracowały dla mnie:

app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', yourExactHostname);
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  next();
});
Eyk Rehbein
źródło
Dodanie X-PINGOTHERdo Access-Control-Allow-Headersbyło dla mnie obowiązkowe (Node.js 6.9 z Express 4.16, Chrome 63). Sprawdź post JakeEldera w tym numerze GitHub: github.com/axios/axios/issues/191#issuecomment-311069164
Frosty Z
5

dla ludzi, którzy nadal nie są w stanie go rozwiązać, ta odpowiedź mi pomogła. odpowiedź dotycząca przepełnienia stosu: 34558264

TLDR; należy ustawić {withCredentials: true}zarówno żądanie GET, jak i POST (pobieranie pliku cookie) zarówno dla axios, jak i dla pobierania.

the_dangoria
źródło
1
To jest kluczowe. Przeoczyłem to w swoim kodzie i spędziłem dużo czasu zastanawiając się, dlaczego { withCredentials: true }żądanie GET nie przyniosło żadnego efektu.
yogmk
1
Bardzo ważny! Jest wiele dyskusji na temat dodawania withCredentials: truedo konfiguracji żądania, ale nie dotyczy to szczegółów. Spędziłem prawie 2 dni próbując rozwiązać problem, dopóki nie natknąłem się na to
rantao
4

Jak sprawić, by Axios automatycznie wysyłało pliki cookie w żądaniach?

zestaw axios.defaults.withCredentials = true;

lub dla jakiejś konkretnej prośby, której możesz użyć axios.get(url,{withCredentials:true})

spowoduje to błąd CORS, jeśli opcja „Access-Control-Allow-Origin” jest ustawiona na symbol wieloznaczny (*). Dlatego upewnij się, że podałeś adres URL, z którego pochodzi Twoje żądanie

na przykład: jeśli twój front-end, który sprawia, że ​​żądanie działa na localhost: 3000, ustaw nagłówek odpowiedzi jako

res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');

również zestaw

res.setHeader('Access-Control-Allow-Credentials',true);
prak
źródło
3

Możesz użyć withCredentialswłaściwości, aby przekazać pliki cookie w żądaniu.

axios.get(`api_url`, { withCredentials: true })

Po ustawieniu { withCredentials: true }możesz napotkać problem z różnymi źródłami. Aby rozwiązać ten problem, musisz użyć

expressApp.use(cors({ credentials: true, origin: "http://localhost:8080" }));

Tutaj możesz przeczytać o withCredentials

Sunil Garg
źródło
2

Pomieszasz te dwie myśli.

Masz „plik cookie reakcji” i „axios”

React-cookie => służy do obsługi pliku cookie po stronie klienta

axios => służy do wysyłania żądań ajax do serwera

Mając te informacje, jeśli chcesz, aby pliki cookie ze strony klienta były również przekazywane po stronie zaplecza, musisz je połączyć.

Uwaga z pliku Readme „React-cookie”:

Izomorficzne ciasteczka!

Aby mieć dostęp do plików cookie użytkownika podczas renderowania na serwerze, możesz użyć plugToRequest lub setRawCookie.

link do pliku readme

Jeśli tego potrzebujesz, świetnie.

Jeśli nie, proszę o komentarz, abym mógł rozwinąć więcej.

Tzook Bar Noy
źródło
Co plugToRequestdokładnie robi? Pomyślałem, że aby uzyskać dostęp do plików cookie na serwerze węzła, wystarczy tylko cookie-parseroprogramowanie pośredniczące (zakładając Express)?
geoboy
2

Więc miałem dokładnie ten sam problem i straciłem około 6 godzin mojego życia na szukaniu, miałem

withCredentials: true

Ale przeglądarka nadal nie zapisała pliku cookie, dopóki z jakiegoś dziwnego powodu nie wpadłem na pomysł, aby przetasować ustawienia konfiguracji:

Axios.post(GlobalVariables.API_URL + 'api/login', {
        email,
        password,
        honeyPot
    }, {
        withCredentials: true,
        headers: {'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json'
    }});

Wygląda na to, że zawsze powinieneś najpierw wysłać klucz „withCredentials”.

Luigi Cordoba Granera
źródło