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.
"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
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
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