2017-03-10 1 views
0

J'utilise le serveur Express.js. Avec cookie-parser j'ai ouvert ce point de terminaisonfetch() ne peut pas configurer les cookies reçus du serveur?

app.get("/s", (req,res) => { 
    res.cookie("bsaSession", req.session.id) 
    res.send("set cookie ok") 
}) 

Quand j'utiliser manuellement le navigateur pour http://localhost:5555/s où j'ai le site Web exécutant la console de débogage du navigateur montre qui a été appliqué le cookie.

enter image description here

Mais quand j'utilise fetch API pour faire l'équivalent, il ne définit pas le cookie.

async trySetCookie() 
    { 
    await fetch("http://localhost:5555/s",{ 
     method: 'GET', 
     credentials: 'same-origin' 
    }) 
    } 

Pourquoi?

+1

"il ne définit pas le cookie" --- comment le savez-vous? Le navigateur a-t-il envoyé le cookie dans les en-têtes de la demande? – zerkms

+0

J'ai regardé dans la console de débogage Safari> Stockage> Cookies. Quand je clique sur le bouton qui appelle 'trySetCookie()' la liste ne change pas. Mais quand je vais directement à cette page, la liste a de nouveaux cookies ajoutés immédiatement. – 5argon

+1

Alors, voyez-vous le 'Set-Cookie' dans les en-têtes de réponse? Ce script fonctionne-t-il sur le même port? – zerkms

Répondre

1

J'ai trouvé la solution. Le cœur de ce problème étant que mon bouton pour déclencher le fetch est sur http://localhost:3000/. Le serveur est sur http://localhost:5555/ (je suis simulant l'environnement réel sur ma propre machine)

Le problème est que ce fetch appel

async trySetCookie() 
    { 
    await fetch("http://localhost:5555/s",{ 
     method: 'GET', 
     credentials: 'same-origin' 
    }) 
    } 

Sans credentials, le navigateur ne peut pas envoyer ou recevoir de cookies via fetch (https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials)

Avec credentials comme same-origin Je peux voir les cookies provenant du serveur dans l'en-tête de réponse Set-Cookie, mais rien n'est stocké dans le navigateur. Une chose étrange est que cette réponse a toujours HttpOnly étiqueté après la chaîne de cookie indépendamment de mes paramètres {httpOnly : true/false} sur le serveur. Dans le cas de l'utilisation manuelle du navigateur à la page pour faire la demande GET, HttpOnly est respectée comme d'habitude, et les cookies sont définis. La solution consiste donc à définir credentials comme include pour permettre l'envoi de cookies d'origine croisée.

async trySetCookie() 
    { 
    await fetch("http://localhost:5555/s",{ 
     method: 'GET', 
     credentials: 'include' 
    }) 
    } 

En outre, sur le côté serveur vous devez autoriser une origine particulière manuellement avec de nouveaux en-têtes:

app.get("/s", (req,res) => { 
    res.cookie("bsaSession", req.session.id, {httpOnly:false}) 
    res.header('Access-Control-Allow-Origin', 'http://localhost:3000') 
    res.header('Access-Control-Allow-Credentials','true' 
    res.send("set") 
}) 

Ne pas le faire entraîne

XMLHttpRequest cannot load http://localhost:5555/s. Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true.

Mais le cookie être défini indépendamment de cette erreur. Toujours agréable d'inclure cet en-tête pour faire taire l'erreur. Si vous utilisez cors middleware pour Express c'est encore plus facile. Vous pouvez simplement utiliser ces options

var corsOptions = { 
    origin: 'http://localhost:3000', 
    credentials: true 
} 

app.use(cors(corsOptions)) 

Et bien sûr credentials: 'include' est encore nécessaire du côté client.