Cookies sur localhost avec domaine explicite

203

Il me manque quelque chose de basique sur les cookies. Sur localhost, lorsque je place un cookie côté serveur et que je spécifie explicitement le domaine comme localhost (ou .localhost). le cookie ne semble pas être accepté par certains navigateurs.

Firefox 3.5: J'ai vérifié la requête HTTP dans Firebug. Ce que je vois c'est:

Set-Cookie:
    name=value;
    domain=localhost;
    expires=Thu, 16-Jul-2009 21:25:05 GMT;
    path=/

ou (lorsque j'ai défini le domaine sur .localhost):

Set-Cookie:
    name=value;
    domain=.localhost;
    expires=Thu, 16-Jul-2009 21:25:05 GMT;
    path=/

Dans les deux cas, le cookie n'est pas stocké.

IE8: Je n'ai utilisé aucun outil supplémentaire, mais le cookie ne semble pas non plus stocké, car il n'est pas renvoyé dans les demandes suivantes.

Opera 9.64: localhost et .localhost fonctionnent tous les deux , mais lorsque je vérifie la liste des cookies dans Préférences, le domaine est défini sur localhost.local même s'il est répertorié sous localhost (dans le regroupement de la liste).

Safari 4: localhost et .localhost fonctionnent , mais ils sont toujours répertoriés comme .localhost dans les préférences. D'autre part, un cookie sans domaine explicite, il est affiché comme juste localhost (pas de point).

Quel est le problème avec localhost? En raison d'un tel nombre d'incohérences, il doit y avoir des règles spéciales impliquant localhost. De plus, je ne vois pas tout à fait pourquoi les domaines doivent être précédés d'un point? La RFC 2109 déclare explicitement que:

La valeur de l'attribut Domaine ne contient aucun point incorporé ou ne commence pas par un point.

Pourquoi? Le document indique qu'il doit faire quelque chose avec la sécurité. Je dois admettre que je n'ai pas lu toute la spécification (peut-être le faire plus tard), mais cela semble un peu étrange. Sur cette base, la configuration de cookies sur localhost serait impossible.

Jan Zich
la source
18
Fil de 6 ans et c'est toujours un problème. J'utilise Chrome v40. Regardez ici .
Gaui
6
Chrome 43 ... toujours un bug.
Evan Carroll
5
Chrome 54 ici, PAS résolu
Vahid Amiri
7
Chrome 73 .. toujours confronté au même problème. :(
Code_Crash
6
11 ans plus tard, ça ne marche toujours pas, les cookies font toujours mal au cul en 2020!
Otto le

Réponses:

248

De par leur conception, les noms de domaine doivent avoir au moins deux points; sinon le navigateur les considérera invalides. (Voir référence sur http://curl.haxx.se/rfc/cookie_spec.html )

Lorsque vous travaillez dessus localhost, le domaine du cookie doit être entièrement omis. Il ne suffit pas de le régler sur ""ou NULLou FALSEau lieu de "localhost".

Pour PHP, voir les commentaires sur http://php.net/manual/en/function.setcookie.php#73107 .

Si vous travaillez avec l'API Java Servlet, n'appelez pas du cookie.setDomain("...")tout la méthode.

Ralph Buchfelder
la source
103
Je ne sais pas pourquoi tout le monde fait + 1, j'ai défini le domaine du cookie sur une chaîne nulle ou fausse ou vide et il ne s'enregistre toujours pas s'il est sur localhost.
Justin le
5
Je ne vois nulle part dans la RFC6265 à propos des deux points du domaine: tools.ietf.org/html/rfc6265#section-5.2.3 .Net dit de le définir sur ".local" pour tous les hôtes de votre domaine local. Ce qui semble cohérent avec Opera / Safari msdn.microsoft.com/en-us/library/ckch3yd2.aspx
MandoMando
10
@Justin: Hm, vous devrez probablement omettre complètement le Domain=paramètre lors de la configuration du cookie. Si vous définissez simplement le domaine sur null ou vide, votre framework enverra peut-être le Domain=paramètre avec cette valeur, au lieu de l'omettre? Vérifiez avec par exemple Firebug.
sleske
2
@Ralph, un million de mercis, ce truc m'a rendu fou pendant quelques heures. Espérons que la définition du domaine sur null (je suis dans une pile de serveurs .Net) fonctionne comme un charme.
Xose Lluis
4
C'est un peu mal formulé. "Définition de null ou false ou chaîne vide" doit lire "Ne pas définir du tout la partie" domaine "du cookie." Par exemple, l'utilisation d'un test simple pour ((domain && domain !== "localhost") ? ";domain="+domain : "")
omettre
36

Je suis globalement d'accord avec @Ralph Buchfelder, mais voici une amplification de cela, par expérience en essayant de répliquer un système avec plusieurs sous-domaines (tels que example.com, fr.example.com, de.example.com) sur ma machine locale ( OS X / Apache / Chrome | Firefox).

J'ai édité / etc / hosts pour pointer certains sous-domaines imaginaires à 127.0.0.1:

127.0.0.1 localexample.com
127.0.0.1 fr.localexample.com
127.0.0.1 de.localexample.com

Si je travaille sur fr.localexample.com et que je laisse le paramètre de domaine de côté, le cookie est stocké correctement pour fr.localexample.com, mais n'est pas visible dans les autres sous-domaines.

Si j'utilise un domaine de ".localexample.com", le cookie est stocké correctement pour fr.localexample.com, et est visible dans d'autres sous-domaines.

Si j'utilise un domaine de "localexample.com", ou lorsque j'essayais un domaine de "localexample" ou "localhost", le cookie n'était pas stocké.

Si j'utilise un domaine de "fr.localexample.com" ou ".fr.localexample.com", le cookie est stocké correctement pour fr.localexample.com et est (correctement) invisible dans les autres sous-domaines.

Donc, l'exigence selon laquelle vous avez besoin d'au moins deux points dans le domaine semble être correcte, même si je ne vois pas pourquoi cela devrait être.

Si quelqu'un veut essayer ceci, voici un code utile:

<html>
<head>
<title>
Testing cookies
</title>
</head>
<body>
<?php
header('HTTP/1.0 200');
$domain = 'fr.localexample.com';    // Change this to the domain you want to test.
if (!empty($_GET['v'])) {
    $val = $_GET['v'];
    print "Setting cookie to $val<br/>";
    setcookie("mycookie", $val, time() + 48 * 3600, '/', $domain);
}
print "<pre>";
print "Cookie:<br/>";
var_dump($_COOKIE);
print "Server:<br/>";
var_dump($_SERVER);
print "</pre>";
?>
</body>
</html>
xgretsch
la source
30

localhost: Vous pouvez utiliser: domain: ".app.localhost"et cela fonctionnera. Le paramètre «domaine» a besoin d'un ou plusieurs points dans le nom de domaine pour définir les cookies. Ensuite , vous pouvez avoir des séances de travail à travers les sous - domaines localhost tels que: api.app.localhost:3000.

AmpT
la source
1
Également testé et fonctionnant sur un serveur node.js, utilisant Express 3.x, enexpress.session({cookie: { domain: '.app.localhost', maxAge: 24 * 60 * 60 * 1000 }})
AmpT
3
CECI devrait être sélectionné comme réponse si vous utilisez des domaines locaux! Mettre un point avant le sous-domaine résout mon problème.
Foxhoundn
1
Alors, d'où vient ce préfixe de la .app.venue? Cela fait-il partie d'un SPEC? Et est-ce applicable à tous les domaines non conformes (ceux sans deux points)? Cela fonctionnera-t-il également avec les anciens navigateurs? : ^)
user2173353
Oh ... je comprends maintenant ... C'est juste une astuce pour tromper les navigateurs. D'ACCORD.
user2173353
15

Lorsqu'un cookie est défini avec un domaine explicite de 'localhost' comme suit ...

Set-Cookie: nom = valeur; domaine = localhost ; expire = Jeu, 16-Juil-2009 21:25:05 GMT; chemin = /

... alors les navigateurs l'ignorent car il n'inclut pas au moins deux périodes et ne fait pas partie des sept domaines de premier niveau spécialement gérés .

... les domaines doivent avoir au moins deux (2) ou trois (3) points pour éviter les domaines de la forme: ".com", ".edu" et "va.us". Tout domaine qui échoue dans l'un des sept domaines de premier niveau spéciaux répertoriés ci-dessous ne nécessite que deux périodes. Tout autre domaine en nécessite au moins trois. Les sept domaines spéciaux de premier niveau sont: "COM", "EDU", "NET", "ORG", "GOV", "MIL" et "INT".

Notez que le nombre de périodes ci-dessus suppose probablement qu'une période de début est nécessaire. Cette période est cependant ignorée dans les navigateurs modernes et elle devrait probablement lire ...

au moins une (1) ou deux (2) périodes

Notez que la valeur par défaut de l'attribut de domaine est le nom d'hôte du serveur qui a généré la réponse du cookie .

Ainsi, une solution de contournement pour les cookies non définis pour localhost consiste simplement à ne pas spécifier d'attribut de domaine et à laisser le navigateur utiliser la valeur par défaut - cela ne semble pas avoir les mêmes contraintes qu'une valeur explicite dans l'attribut de domaine.

Scott Munro
la source
Je n'ai pas DV, mais je suppose que la raison pour laquelle d'autres l'ont fait est que votre réponse n'ajoute pas vraiment beaucoup de valeur. L'exigence des deux périodes et le fait de laisser l'attribut de domaine vide ont tous deux été abordés dans d'autres réponses. En outre, les éléments que vous avez ajoutés à propos d'un domaine de premier niveau semblent être incorrects. D'après mon expérience, ce n'est pas une exigence.
TTT
@TTT Vous ne savez pas si vous êtes arrivé au bit dans ma réponse où je dis qu'il devrait y avoir au moins 1 ou deux périodes selon le TLD parce que les périodes de début sont ignorées? J'ai donc fourni quelques informations générales sur le problème et ajouté un point que je ne pense pas être traité ailleurs - les règles sont différentes pour un domaine explicite et celui sur lequel le navigateur par défaut. On dirait que cela m'ajoute de la valeur.
Scott Munro
1
Laisser le domaine nul (ne pas le définir du tout) n'oblige PAS Chrome à conserver le cookie pour localhost. Il l'ignore toujours. Notez que cela ne s'applique qu'aux cookies "permanents" (ceux qui définissent une date d'expiration), car il se suspendra aux cookies de "session" pour localhost (ceux qui ne définissent pas de date d'expiration).
Triynko
4

Si vous définissez un cookie d'un autre domaine (c'est-à-dire que vous définissez le cookie en effectuant une requête d'origine croisée XHR), vous devez vous assurer que vous définissez l' withCredentialsattribut sur true sur la XMLHttpRequest que vous utilisez pour récupérer le cookie comme décrit ici

Aidan Ewen
la source
oui même avec ça. Cela ne fonctionne toujours pas avec les demandes inter-domaines. Navigateur - Safari, IE 11
Rohit Kumar
3

Les résultats que j'avais varient selon le navigateur.

Chrome- 127.0.0.1 fonctionnait mais localhost .localhost et "" ne le faisaient pas. Firefox- .localhost fonctionnait mais localhost, 127.0.0.1 et "" ne fonctionnaient pas.

N'ont pas testé dans Opera, IE ou Safari


la source
3
Je viens de le tester avec Chrome V.22.0.1229.94 m: définir un cookie pour localhost sans donner de Domain=paramètre fonctionne. Domain=fonctionne également, mais Domain=localhostne fonctionne pas.
sleske
3

J'ai passé beaucoup de temps à résoudre ce problème moi-même.

Utiliser PHP, et rien sur cette page n'a fonctionné pour moi. J'ai finalement réalisé dans mon code que le paramètre «secure» de session_set_cookie_params () de PHP était toujours réglé sur TRUE.

Comme je ne visitais pas localhost avec https, mon navigateur n'accepterait jamais le cookie. Donc, j'ai modifié cette partie de mon code pour définir conditionnellement le paramètre «secure» basé sur $ _SERVER ['HTTP_HOST'] étant 'localhost' ou non. Fonctionne bien maintenant.

J'espère que ça aidera quelqu'un.

James Jacobson
la source
2

J'ai eu beaucoup plus de chance de tester localement en utilisant 127.0.0.1 comme domaine. Je ne sais pas pourquoi, mais j'ai eu des résultats mitigés avec localhost et .localhost, etc.

toby
la source
2

vous pouvez utiliser localhost.orgou plutôt .localhost.orgil se résoudra toujours à127.0.0.1

qoomon
la source
1

Aucun des correctifs suggérés n'a fonctionné pour moi - le définir sur null, false, ajouter deux points, etc. - n'a pas fonctionné.

En fin de compte, je viens de supprimer le domaine du cookie s'il s'agit de localhost et cela fonctionne maintenant pour moi dans Chrome 38 .

Code précédent (n'a pas fonctionné):

document.cookie = encodeURI(key) + '=' + encodeURI(value) + ';domain=.' + document.domain + ';path=/;';

Nouveau code (fonctionne maintenant):

 if(document.domain === 'localhost') {
        document.cookie = encodeURI(key) + '=' + encodeURI(value) + ';path=/;' ;
    } else {
        document.cookie = encodeURI(key) + '=' + encodeURI(value) + ';domain=.' + document.domain + ';path=/;';
    }
DJ_Polly
la source
1

Il y a un problème sur Chromium ouvert depuis 2011 , si vous définissez explicitement le domaine en tant que 'localhost', vous devez le définir comme falseou undefined.

Bruno Peres
la source
C'était la seule solution qui a fonctionné pour moi, le réglage Domain: undefinedetPath: '/'
TheoG
1

J'ai eu le même problème et je l'ai résolu en mettant 2 points dans le nom du cookie lui-même sans spécifier de domaine.

set-cookie: name.s1.s2=value; path=/; expires=Sun, 12 Aug 2018 14:28:43 GMT; HttpOnly
Éric B.
la source
1

Il semble y avoir un problème lorsque vous utilisez https://<local-domain>et ensuite http://<local-domain>. Le http://site n'envoie pas de cookies avec les demandes une fois que le https://site les a définis. Forcer le rechargement et vider le cache n'aide pas. Seule la suppression manuelle des cookies fonctionne. De plus, si je les efface sur la https://page, la http://page recommence à fonctionner.

Semble être lié aux "cookies sécurisés stricts". Bonne explication ici . Il a été publié dans Chrome 58 le 19/04/2017.

Il semble que Chrome enregistre en fait à la fois les cookies sécurisés et les cookies non sécurisés, car il affichera les cookies appropriés en fonction du protocole de la page lorsque vous cliquez sur l'icône de la barre d'adresse.

Mais Developer tools > Application > Cookiesne montrera pas de cookie non sécurisé lorsqu'il existe un cookie sécurisé du même nom pour le même domaine, ni n'enverra le cookie non sécurisé avec des demandes. Cela semble être un bogue de Chrome, ou si ce comportement est attendu, il devrait y avoir un moyen d'afficher les cookies sécurisés lorsqu'ils sont sur une httppage et une indication qu'ils sont remplacés.

La solution de contournement consiste à utiliser des cookies nommés différents selon qu'ils sont destinés à un site http ou https, et à les nommer spécifiquement pour votre application. Un __Secure-préfixe indique que le cookie doit être strictement sécurisé et constitue également une bonne pratique car sécurisé et non sécurisé ne se heurteront pas. Les préfixes présentent également d' autres avantages .

L'utilisation de /etc/hostsdomaines différents pour l'accès https par rapport à l'accès http fonctionnerait également, mais une https://localhostvisite accidentelle empêchera tous les cookies du même nom de fonctionner sur les http://localhostsites - ce n'est donc pas une bonne solution de contournement.

J'ai déposé un rapport de bogue Chrome .

Vaughan
la source
1

Après beaucoup d'expérimentation et de lecture de divers articles, cela a fonctionné. Je pourrais définir plusieurs cookies, les relire et définir l'heure négative et les supprimer.

func addCookie(w http.ResponseWriter, name string, value string) {
    expire := time.Now().AddDate(0, 0, 1)
    cookie := http.Cookie{
       Name:    name,
       Value:   value,
       Expires: expire,
       Domain:  ".localhost",
       Path:    "/",
    }
    http.SetCookie(w, &cookie)
}
Saied
la source
Ça ne marche pas pour moi. En utilisant "..", "localhost", ".localhost", rien ne semble fonctionner.
Kugel
J'ai fini par utiliser le Gestionnaire de Session Alex Edwards (dans mon cas avec MySQL, mais il vous donne d'autres options) et cela fonctionne très bien. Vous voudrez peut-être envisager le même alexedwards.net/blog/scs-session-manager
Saied
J'ai modifié / etc / hosts pour qu'il fonctionne avec localhost.com, ce qui fonctionne bien aussi.
Kugel
1

La seule chose qui a fonctionné pour moi était de mettre Path=/le cookie.

De plus, la valeur par défaut d'un attribut de chemin semble être différente d'un navigateur à l'autre bien que je n'en ai testé que deux (Firefox et Chrome).

Chrome essaie de définir un cookie tel quel; si l' pathattribut est omis dans l'en- Set-Cookietête, il ne sera pas stocké et ignoré.

Cependant, Firefox stocke un cookie même sans pathattribut explicite . Il l'a simplement défini avec le chemin demandé; mon URL de demande était /api/v1/userset le chemin a été défini sur /api/v1automatiquement.

Quoi qu'il en soit, les deux navigateurs fonctionnaient quand pathétait réglé sur /même sans domaine explicite, c'est à dire Domain=localhostou quelque chose. Il existe donc des différences dans la manière dont chaque navigateur gère les cookies.

이준형
la source
0

document.cookie = nom_valeur + "=" + valeur + ";" + expire + "; domaine =; chemin = /";

ce "domaine =; chemin = /"; prendra le domaine dynamique car son cookie fonctionnera dans le sous-domaine. si vous voulez tester dans localhost cela fonctionnera

Abhishek SInha
la source
0

Aucune des réponses ici n'a fonctionné pour moi. Je l'ai corrigé en mettant mon PHP comme toute première chose dans la page.

Comme les autres en-têtes, les cookies doivent être envoyés avant toute sortie de votre script (il s'agit d'une restriction de protocole). Cela nécessite que vous appeliez cette fonction avant toute sortie, y compris les balises et ainsi que les espaces.

Depuis http://php.net/manual/en/function.setcookie.php

john ktejik
la source
cela n'a rien à voir avec le problème, cela ne fait tout simplement pas l'erreur d'envoyer une autre sortie avant les en
Marnes
0

Je jouais un peu.

Set-Cookie: _xsrf=2|f1313120|17df429d33515874d3e571d1c5ee2677|1485812120; Domain=localhost; Path=/

fonctionne dans Firefox et Chrome à partir d'aujourd'hui. Cependant, je n'ai pas trouvé de moyen de le faire fonctionner avec curl. J'ai essayé Host-Header et --resolve, pas de chance, toute aide appréciée.

Cependant, cela fonctionne dans curl, si je le règle sur

Set-Cookie: _xsrf=2|f1313120|17df429d33515874d3e571d1c5ee2677|1485812120; Domain=127.0.0.1; Path=/

au lieu. (Ce qui ne fonctionne pas avec Firefox.)

Micha
la source
0

Autre détail important, expires = doit utiliser le format de date et d'heure suivant: Wdy, DD-Mon-YYYY HH: MM: SS GMT ( RFC6265 - Section 4.1.1 ).

Set-Cookie:
  name=value;
  domain=localhost;
  expires=Thu, 16-07-2019 21:25:05 GMT;
  path=/
Tralamazza
la source
5
-1 La spécification actuelle des cookies est la RFC 6265, tools.ietf.org/html/rfc6265 , qui stipule explicitement que les années à 4 chiffres sont autorisées. C'est donc une mauvaise idée d'utiliser des années à 2 chiffres, que différents navigateurs interpréteront différemment.
sleske
Correct. Réf RFC6265 section 4.1.1
Zen Cart
4
Correct, mais en juin 2011, je n'ai pas trouvé cette RFC. Donc, bien que cette information soit maintenant incorrecte, à l'époque où je l'ai écrit, elle ne l'était pas.
Tralamazza
4
Ne le prenez pas comme une légère, les choses changent et nous devons tous nous assurer que les réponses restent à jour. Mettez simplement à jour votre réponse avec les dernières informations que @sleske vous a fournies et remerciez-le pour son aide.
Matthew Purdon
0

J'ai essayé toutes les options ci-dessus. Ce qui a fonctionné pour moi était:

  1. Assurez-vous que la requête au serveur est définie sur true pour withCredentials . XMLHttpRequest d'un domaine différent ne peut pas définir de valeurs de cookie pour son propre domaine à moins que withCredentials ne soit défini sur true avant d'effectuer la demande.
  2. Ne pas fixer Domain
  3. Ensemble Path=/

En- Set-Cookietête résultant :

Set-Cookie: session_token=74528588-7c48-4546-a3ae-4326e22449e5; Expires=Sun, 16 Aug 2020 04:40:42 GMT; Path=/
Josiah
la source
0

Le cookie doit spécifier un SameSiteattribut, la Nonevaleur étant la valeur par défaut, mais les versions récentes du navigateur ont défini Laxla valeur par défaut pour avoir une défense raisonnablement robuste contre certaines classes d'attaques de falsification de requête intersites (CSRF).

En même temps que SameSite=Laxvous devriez également avoir Domain=localhost, votre cookie sera associé localhostet conservé. Ça devrait ressembler a quelque chose comme ca:

document.cookie = `${name}=${value}${expires}; Path=/; Domain=localhost; SameSite=Lax`;

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite

jwallet
la source