Cookies on localhost with explicit domain

2018-12-31 07:45发布

I must be missing some basic thing about cookies. On localhost, when I set a cookie on server side and specify the domain explicitly as localhost (or .localhost). the cookie does not seem to be accepted by some browsers.

Firefox 3.5: I checked the HTTP request in Firebug. What I see is:

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

or (when I set the domain to .localhost):

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

In either case, the cookie is not stored.

IE8: I did not use any extra tool, but the cookie does not seem to be stored as well, because it’s not being sent back in subsequent requests.

Opera 9.64: Both localhost and .localhost work, but when I check the list of cookies in Preferences, the domain is set to localhost.local even though it’s listed under localhost (in the list grouping).

Safari 4: Both localhost and .localhost work, but they are always listed as .localhost in Preferences. On the other hand, a cookie without an explicit domain, it being shown as just localhost (no dot).

What is the problem with localhost? Because of such a number of inconsistencies, there must be some special rules involving localhost. Also, it’s not completely clear to me why domains must be prefixed by a dot? RFC 2109 explicitly states that:

The value for the Domain attribute contains no embedded dots or does not start with a dot.

Why? The document indicates that it has to do something with security. I have to admit that I have not read the entire specification (may do it later), but it sounds a bit strange. Based on this, setting cookies on localhost would be impossible.

15条回答
琉璃瓶的回忆
2楼-- · 2018-12-31 08:02

I had much better luck testing locally using 127.0.0.1 as the domain. I'm not sure why, but I had mixed results with localhost and .localhost, etc.

查看更多
皆成旧梦
3楼-- · 2018-12-31 08:03

Spent a great deal of time troubleshooting this issue myself.

Using PHP, and Nothing on this page worked for me. I eventually realized in my code that the 'secure' parameter to PHP's session_set_cookie_params() was always being set to TRUE.

Since I wasn't visiting localhost with https my browser would never accept the cookie. So, I modified that portion of my code to conditionally set the 'secure' param based on $_SERVER['HTTP_HOST'] being 'localhost' or not. Working well now.

I hope this helps someone.

查看更多
像晚风撩人
4楼-- · 2018-12-31 08:05

There seems to be an issue when you use https://<local-domain> and then http://<local-domain>. The http:// site does not send cookies with requests after https:// site sets them. Force reload and clear cache doesn't help. Only manual clearing of cookies works. Also, if I clear them on the https:// page, then http:// page starts working again.

Looks to be related to "Strict secure cookies". Good explanation here. It was released in Chrome 58 on 2017-04-19.

It looks like Chrome does in fact record both secure cookies and non-secure cookies as it will show the correct cookies depending on the page's protocol when clicking the address bar icon.

But Developer tools > Application > Cookies will not show a non-secure cookie when there is a secure cookie of the same name for the same domain, nor will it send the non-secure cookie with any requests. This seems like a Chrome bug, or if this behavior is expected, there should be some way to view the secure cookies when on a http page and an indication that they are being overridden.

Workaround is to use different named cookies depending on if they are for an http site or https site, and to name them specific to your app. A __Secure- prefix indicates that the cookie should be strictly secure, and is also a good practice because secure and non-secure won't collide. There are other benefits to prefixes too.

Using different /etc/hosts domains for https vs. http access would work too, but one accidental https://localhost visit will prevent any cookies of the same names to work on http://localhost sites - so this is not a good workaround.

I have filed a Chrome bug report.

查看更多
骚的不知所云
5楼-- · 2018-12-31 08:06

When a cookie is set with an explicit domain of 'localhost' as follows...

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

...then browsers ignore it because it does not include at least two periods and is not one of seven specially handled, top level domains.

...domains must have at least two (2) or three (3) periods in them to prevent domains of the form: ".com", ".edu", and "va.us". Any domain that fails within one of the seven special top level domains listed below only require two periods. Any other domain requires at least three. The seven special top level domains are: "COM", "EDU", "NET", "ORG", "GOV", "MIL", and "INT".

Note that the number of periods above probably assumes that a leading period is required. This period is however ignored in modern browsers and it should probably read...

at least one (1) or two (2) periods

Note that the default value for the domain attribute is the host name of the server which generated the cookie response.

So a workaround for cookies not being set for localhost is to simply not specify a domain attribute and let the browser use the default value - this does not appear to have the same constraints that an explicit value in the domain attribute does.

查看更多
何处买醉
6楼-- · 2018-12-31 08:10

None of the answers here worked for me. I fixed it by putting my PHP as the very very first thing in the page.

Like other headers, cookies must be sent before any output from your script (this is a protocol restriction). This requires that you place calls to this function prior to any output, including and tags as well as any whitespace.

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

查看更多
栀子花@的思念
7楼-- · 2018-12-31 08:11

I broadly agree with @Ralph Buchfelder, but here's some amplification of this, by experiment when trying to replicate a system with several subdomains (such as example.com, fr.example.com, de.example.com) on my local machine (OS X / Apache / Chrome|Firefox).

I've edited /etc/hosts to point some imaginary subdomains at 127.0.0.1:

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

If I am working on fr.localexample.com and I leave the domain parameter out, the cookie is stored correctly for fr.localexample.com, but is not visible in the other subdomains.

If I use a domain of ".localexample.com", the cookie is stored correctly for fr.localexample.com, and is visible in other subdomains.

If I use a domain of "localexample.com", or when I was trying a domain of just "localexample" or "localhost", the cookie was not getting stored.

If I use a domain of "fr.localexample.com" or ".fr.localexample.com", the cookie is stored correctly for fr.localexample.com and is (correctly) invisible in other subdomains.

So the requirement that you need at least two dots in the domain appears to be correct, even though I can't see why it should be.

If anyone wants to try this out, here's some useful code:

<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>
查看更多
登录 后发表回答