Récupérer l'API avec cookie

201

J'essaie la nouvelle API Fetch mais j'ai des problèmes avec les cookies. Plus précisément, après une connexion réussie, il y a un en-tête Cookie dans les demandes futures, mais Fetch semble ignorer ces en-têtes, et toutes mes demandes effectuées avec Fetch ne sont pas autorisées.

Est-ce parce que Fetch n'est toujours pas prêt ou Fetch ne fonctionne pas avec les cookies?

Je construis mon application avec Webpack. J'utilise également Fetch dans React Native, qui n'a pas le même problème.

Khanetor
la source

Réponses:

280

Fetch n'utilise pas de cookie par défaut. Pour activer les cookies, procédez comme suit:

fetch(url, {
  credentials: "same-origin"
}).then(...).catch(...);
Khanetor
la source
55
same-origin ne fonctionne plus, incluez le fait (voir la réponse de @ Jerry): développeurs.google.com
web
7
@jpic: 'include' ne fonctionne que pour les requêtes cross-origin, mais pas pour les requêtes de même origine. Documents
HoldOffHunger
Quelle est alors la raison d'avoir des cookies httponly s'ils sont lisibles en js avec fetch?
Martin Bajcar
4
Je crois same-origin(ce qui fonctionne toujours) signifie que plus d'en-têtes seront respectés (cookies, etc.) mais votre code aura un accès limité à la réponse.
Coderer
2
@JohnBalvinAriasThx. Comme je l'ai compris plus tard, avoir un cookie httponly signifie qu'il n'est pas lisible par document.cookie, mais toujours disponible pour ajax ou pour récupérer des requêtes.
Martin Bajcar
186

En plus de la réponse de @ Khanetor, pour ceux qui travaillent avec des demandes d'origine croisée: credentials: 'include'

Exemple de demande de récupération 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
la source
9
comment définissez-vous le cookie?
pomo
2
Le cookie est défini du côté serveur. Dans mon cas, j'utilisais des cookies httponly.
Khanetor
3
@Khanetor puis-je définir des cookies en utilisant le document.cookie par javascript, puis envoyer la demande?
ospider
@ospider Vous pouvez l'envoyer dans l'en-tête.
10101010
2
@ospider J'ai trouvé qu'il suffisait de définir la valeur dans document.cookiepour qu'elle soit incluse dans les demandes.
skwidbreth
36

Je viens de résoudre. Juste deux f. jours de brutforce

Pour moi, le secret était de suivre:

  1. J'ai appelé POST / api / auth et j'ai vu que les cookies ont été reçus avec succès.

  2. Ensuite, appelez GET / api / users / with credentials: 'include'et obtenu 401 unauth, car aucun cookie n'a été envoyé avec la demande.

La CLE est également à définir credentials: 'include'pour le premier /api/authappel.

user1671599
la source
1
J'ai exactement votre problème. Le cookie de session n'est jamais envoyé sur la demande de données GET. donc 401. J'ai essayé Axios et Fetch. même résultat. 2 possibilités: le login POST ne stocke pas le cookie reçu ou les données GET suivantes n'envoient pas le cookie stocké
Rhubarb65
@ Rhubarb65, pour gagner, vous devez spécifier credentials: 'include'pour le premierPOST /api/auth
user1671599
Oui, j'avais ça mais ça en veut assez. J'utilise un proxy devserver (client Http)
Rhubarb65
Oui, j'avais des informations d'identification mais ce n'était pas suffisant. J'utilisais un proxy devserver pour passer CORS: (client http) - proxy - (serveur https). Je pense que cela signifie que le cookie sessionid du serveur n'a pas été défini dans le navigateur car les cookies sécurisés nécessitent https. J'ai donc ajouté le drapeau https: true dans le proxy devserver et cela l'a corrigé
Rhubarb65
1
Eh bien, bravo. Votre réponse signifiait qu'il ne m'a fallu qu'un jour de force brute. :)
Michael
16

Si vous lisez ceci en 2019, credentials: "same-origin"est la valeur par défaut.

fetch(url).then
Alextrastero
la source
1
Mais notez que tout le monde n'utilise pas un navigateur suffisamment mis à jour. Je suis tombé sur cette question parce que ma propre version de Firefox (60.x, la plus récente de Debian Stretch) ne définit pas cela par défaut.
philh
2

Il suffit d'ajouter les bonnes réponses ici pour les .net webapi2utilisateurs.

Si vous utilisez corsparce que votre site client est servi à partir d'une adresse différente de la vôtre, webapivous devez également inclure SupportsCredentials=truela configuration côté serveur.

        // 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
la source
0

Cela fonctionne pour moi:

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

Ensuite, construisez votre appel:

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
la source