J'ai un problème avec la mise en place de cookies via express. J'utilise Este.js dev stack
Et j'essaie de définir un cookie dans la route d'authentification /login
De l'API. Voici le code que j'utilise dans /api/v1/auth/login
route
res.cookie('token', jwt.token, {expires: new Date(Date.now() + 9999999)});
res.status(200).send({user, token: jwt.token});
Dans src/server/main.js
J'ai enregistré cookie-parser
Comme premier middleware
app.use(cookieParser());
L'en-tête de réponse pour la route /api/v1/auth/login
Contient
Set-Cookie:token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ..
mais le cookie n'est pas enregistré dans le navigateur (document.cookie
est vide, également l'onglet Resources - Cookies
dans les outils de développement est vide ) :(
EDIT: J'ai constaté que lorsque j'appelle ceci dans /api/v1/auth/login
(Sans appeler res.send
Ou res.json
)
res.cookie('token', jwt.token, {expires: new Date(Date.now() + 9999999), httpOnly: false});
next();
puis le cookie est défini ET l'en-tête de réponse a défini X-Powered-By:Este.js
... cela définit esteMiddleware
dans expres frontend render part .
Lorsque j'utilise res.send
res.cookie('token', jwt.token, {expires: new Date(Date.now() + 9999999), httpOnly: false}).send({user, token: jwt.token});`
next();
alors j'obtiens l'erreur Can't set headers after they are sent.
parce que la méthode send
est utilisée, donc le rendu frontal renvoie cette erreur.
Mais je dois envoyer des données à partir de l'API, alors comment puis-je gérer cela?
Certains peuvent-ils m'aider s'il vous plaît? Merci!
J'ai eu le même problème. La réponse du serveur est fournie avec un jeu de cookies:
Set-Cookie:my_cookie=HelloWorld; Path=/; Expires=Wed, 15 Mar 2017 15:59:59 GMT
Mais le cookie n'a pas été enregistré par un navigateur.
Voilà comment je l'ai résolu.
J'utilise fetch
dans un code côté client. Si vous ne spécifiez pas credentials: 'include'
dans les options fetch
, les cookies ne sont ni envoyés au serveur ni enregistrés par un navigateur, bien que la réponse du serveur définisse des cookies.
Exemple:
var headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
return fetch('/your/server_endpoint', {
method: 'POST',
mode: 'same-Origin',
redirect: 'follow',
credentials: 'include', // Don't forget to specify this if you need cookies
headers: headers,
body: JSON.stringify({
first_name: 'John',
last_name: 'Doe'
})
})
J'espère que cela aide quelqu'un.
je travaille avec express 4 et le noeud 7.4 et angulaire, j'ai eu le même problème pour moi aider ceci:
a) côté serveur: dans le fichier app.js je donne des en-têtes à toutes les réponses comme:
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', req.headers.Origin);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
cela doit avoir avant tout routeur.
J'ai vu de nombreux en-têtes ajoutés:
res.header("Access-Control-Allow-Headers","*");
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
mais je n'en ai pas besoin,
b) lorsque vous définissez un cookie, vous devez ajouter httpOnly: false, comme:
res.cookie( key, value,{ maxAge: 1000 * 60 * 10, httpOnly: false });
c) côté client: dans send ajax, vous devez ajouter: "withCredentials: true", comme:
$http({
method: 'POST',
url: 'url,
withCredentials: true,
data : {}
}).then(function(response){
// code
}, function (response) {
// code
});
bonne chance.
Il y a quelques problèmes:
httpOnly : false
sera pas accessible via document.cookie
dans le navigateur. Il sera toujours envoyé avec des requêtes HTTP, et si vous vérifiez les outils de développement de votre navigateur, vous y trouverez probablement le cookie (dans Chrome ils peuvent être trouvés dans le Ressources onglet des outils de développement);next()
que vous appelez ne doit être utilisée que si vous souhaitez différer l'envoi d'une réponse à une autre partie de votre application qui, à en juger par votre code, n'est pas ce que vous voulez.Donc, il me semble que cela devrait résoudre vos problèmes:
res.cookie('token', jwt.token, {
expires : new Date(Date.now() + 9999999),
httpOnly : false
});
res.status(200).send({ user, token: jwt.token });
En remarque: il y a une raison pour que httpOnly
passe par défaut à true
(pour empêcher les scripts XSS malveillants d'accéder aux cookies de session et autres). Si vous n'avez pas de très bonnes raisons d'accéder au cookie via JS côté client, ne le définissez pas sur false
.
Vérifiez la taille de votre cookie.
Pour moi, la façon dont je générais un jeton d'authentification à stocker dans mon cookie entraînait une augmentation de la taille du cookie avec les tentatives de connexion suivantes, ce qui finissait par empêcher le navigateur de définir le cookie car il était trop gros.
app.post('/api/user/login',(req,res)=>{
User.findOne({'email':req.body.email},(err,user)=>{
if(!user) res.json({message: 'Auth failed, user not found'})
user.comparePassword(req.body.password,(err,isMatch)=>{
if(err) throw err;
if(!isMatch) return res.status(400).json({
message:'Wrong password'
});
user.generateToken((err,user)=>{
if(err) return res.status(400).send(err);
res.cookie('auth',user.token).send('ok')
})
})
})
});
le serveur donne une réponse ok mais le cookie n'est pas stocké dans le navigateur
Ajoutez Postman Interceptor Extension à chrome qui permet à postman de stocker des cookies dans le navigateur et de récupérer les demandes d'utilisation.