API mit Cookie abrufen

198

Ich probiere die neue Fetch-API aus, habe aber Probleme mit Cookies. Insbesondere nach einer erfolgreichen Anmeldung gibt es in zukünftigen Anforderungen einen Cookie-Header, aber Fetch scheint diese Header zu ignorieren, und alle meine mit Fetch gestellten Anforderungen sind nicht autorisiert.

Liegt es daran, dass Fetch noch nicht bereit ist oder Fetch nicht mit Cookies funktioniert?

Ich baue meine App mit Webpack. Ich verwende auch Fetch in React Native, das nicht das gleiche Problem hat.

Khanetor
quelle

Antworten:

279

Fetch verwendet standardmäßig kein Cookie. Gehen Sie folgendermaßen vor, um Cookies zu aktivieren:

fetch(url, {
  credentials: "same-origin"
}).then(...).catch(...);
Khanetor
quelle
54
Same
7
@jpic: 'include' funktioniert nur für Anfragen zwischen verschiedenen Ursprüngen, nicht jedoch für Anfragen mit demselben Ursprung. Offizielle Dokumente: github.com/github/fetch#sending-cookies
HoldOffHunger
Was ist dann der Grund, nur http-Cookies zu haben, wenn diese in js mit fetch lesbar sind?
Martin Bajcar
4
Ich glaube , same-origin(was tut immer noch Arbeit) bedeutet , dass mehr Header (Cookies, etc.) eingehalten werden , aber Ihr Code wird nur begrenzten Zugang zu der Antwort hat.
Coderer
2
@ JohnBalvinAriasThx. Wie ich später verstanden habe, bedeutet Cookie httponly, dass es nicht lesbar ist document.cookie, aber dennoch für Ajax- oder Abrufanfragen verfügbar ist.
Martin Bajcar
183

Zusätzlich zur Antwort von @ Khanetor für diejenigen, die mit Cross-Origin-Anfragen arbeiten: credentials: 'include'

Beispiel für eine JSON-Abrufanforderung:

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
quelle
9
Wie setzen Sie den Cookie?
pomo
2
Das Cookie wird serverseitig gesetzt. In meinem Fall habe ich nur http-Cookies verwendet.
Khanetor
3
@ Khanetor Kann ich Cookies mit der Datei document.cookie per Javascript setzen und dann die Anfrage senden?
ospider
@ospider Sie können es in der Kopfzeile senden.
10101010
2
@ospider Ich fand, dass document.cookiees ausreicht , nur den Wert in festzulegen , um ihn in die Anforderungen aufzunehmen.
Skwidbreth
35

Habe gerade gelöst. Nur zwei f. Tage der Brutforce

Für mich lag das Geheimnis in Folgendem:

  1. Ich habe POST / api / auth angerufen und festgestellt, dass Cookies erfolgreich empfangen wurden.

  2. Rufen Sie dann GET / api / users / with auf credentials: 'include'und erhalten Sie 401 unauth, da mit der Anfrage keine Cookies gesendet wurden.

Der SCHLÜSSEL soll auch credentials: 'include'für den ersten /api/authAnruf eingestellt werden.

user1671599
quelle
1
Ich habe genau dein Problem. Das Sitzungscookie wird niemals bei der GET-Datenanforderung gesendet. Also 401. Ich habe Axios und Fetch ausprobiert. gleiches Ergebnis. 2 Möglichkeiten: Der Login-POST speichert das empfangene Cookie nicht oder die folgenden GET-Daten senden das gespeicherte Cookie nicht
Rhubarb65
@ Rhubarb65, um dies zu gewinnen, sollten Sie credentials: 'include'für den ersten angebenPOST /api/auth
user1671599
Ja, das hatte ich, aber es will genug. Ich benutze einen Devserver-Proxy (Client-
HTTP
Ja, ich hatte Anmeldeinformationen, aber es war nicht genug. Ich habe einen Devserver-Proxy verwendet, um an CORS vorbei zu kommen: (Client http) - Proxy - (Server https). Ich glaube, dies bedeutete, dass das Sessionid-Cookie vom Server nicht im Browser gesetzt wurde, da sichere Cookies https erfordern. Also habe ich das Flag https: true im Devserver-Proxy hinzugefügt und das hat es behoben
Rhubarb65
1
Nun Prost! Ihre Antwort bedeutete, dass ich nur einen Tag Bruteforce brauchte. :)
Michael
15

Wenn Sie dies im Jahr 2019 lesen, credentials: "same-origin"ist dies der Standardwert.

fetch(url).then
alextrastero
quelle
Beachten Sie jedoch, dass nicht jeder einen ausreichend aktualisierten Browser verwendet. Ich bin auf diese Frage gestoßen, weil meine eigene Version von Firefox (60.x, die neueste in Debian Stretch) dies nicht standardmäßig festlegt.
Philh
2

Fügen Sie hier einfach die richtigen Antworten für .net webapi2Benutzer hinzu.

Wenn Sie verwenden, corsweil Ihre Client-Site von einer anderen Adresse als Ihrer bereitgestellt wird, webapimüssen Sie auch SupportsCredentials=truedie serverseitige Konfiguration einbeziehen.

        // 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
quelle
0

Das funktioniert bei mir:

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;
}

Dann bauen Sie Ihren Anruf auf:

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
quelle