使用 PHP 设置 Cookie 时出现问题

发布于 2024-08-04 03:38:30 字数 1132 浏览 4 评论 0原文

我在两个“域”本地工作。我的计算机上有 enterprise.local 和 application.local 虚拟主机,我需要为“local”或“.local”设置域 cookie,但在正确设置 cookie 时遇到了一些问题。在 application.local 中,我有这个:

setcookie( 'iPlanetDirectoryPro', trim( $token_id ), '0', '/', '.local' );
header( 'Location: /adcom-sso' );

我也尝试过这个:

header( 'Set-Cookie: iPlanetDirectoryPro=' . trim( $token_id ) . '; path=/' );
header( 'Location: /adcom-sso' );

使用 setcookie(),没有设置 cookie。使用 Set-Cookie 标头,可以设置 cookie。我已经从两者中删除了重定向,结果永远不会改变。它适用于Set-Cookie,但不适用于setcookie()。这很好,因为我并没有真正偏好使用哪种解决方案,但在 Set-Cookie 解决方案中,一旦我添加域,它就会崩溃

header( 'Set-Cookie: iPlanetDirectoryPro=' . trim( $token_id ) . '; path=/; domain=local' );

:在域值中,我收到标头错误:

Header may not contain more than a single header, new line detected.

我已尝试将域值设置为“local”和“.local”。行为没有改变。

我很少需要显式访问 cookie,所以我希望我只是错过了一些明显的东西,但我肯定没有看到它。任何见解将不胜感激。

更新:我想我已经进一步缩小了范围。似乎只要我不包含域值,这两种方法都可以工作。使用“local”或“.local”作为 cookie 的特定域是否会出现问题?

I'm working locally across two "domains". I have enterprise.local and application.local virtual hosts on my machine and I need to set a domain cookie for "local" or ".local" I'm having some trouble getting the cookie to set properly, though. In application.local, I have this:

setcookie( 'iPlanetDirectoryPro', trim( $token_id ), '0', '/', '.local' );
header( 'Location: /adcom-sso' );

I've also tried this:

header( 'Set-Cookie: iPlanetDirectoryPro=' . trim( $token_id ) . '; path=/' );
header( 'Location: /adcom-sso' );

Using setcookie(), no cookie is ever set. Using the Set-Cookie header, the cookie is set. I've removed the redirection from both and the result never changes. It works for Set-Cookie, but not for setcookie(). That would be fine since I don't really have a preference which solution I use, but in the Set-Cookie solution, as soon as I add a domain it all breaks down:

header( 'Set-Cookie: iPlanetDirectoryPro=' . trim( $token_id ) . '; path=/; domain=local' );

As soon as I add in the domain value, I get a header error:

Header may not contain more than a single header, new line detected.

I've tried the domain value as "local" and ".local". The behavior doesn't change.

I rarely have to explicitly access cookies, so I hope I'm just missing something obvious, but I surely don't see it. Any insight would be much appreciated.

UPDATE: I think I've narrowed this down a bit further. It seems that both ways will work as long as I don't include a domain value. Could there be a problem with using "local" or ".local" as the specific domain for the cookie?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

菊凝晚露 2024-08-11 03:38:30

编辑:
我现在查看了 RFC2109,4.3.2 拒绝 Cookie:

  • Domain 属性的值不包含嵌入点或
    不以点开头。

    ...

  • 带有 Domain=.com 或 Domain=.com. 的 Set-Cookie 始终是
    被拒绝,因为没有嵌入点。

由于安全问题,浏览器似乎拒绝“.local”。要为域设置 cookie,它必须至少有两个点(例如“.cookiedomain.local”)。

AFAIK 不可能从一个子域(例如 one.local)为另一个子域(例如 another.local)设置 cookie。为了克服这个问题,您可以将用户重定向到一个 cookie 域,该域设置/获取所有 cookie,并使用 url 中包含的 cookie 数据作为查询参数再次将用户重定向到他们来自的位置。微软在自己的域(msn.com、microsoft.com)上就是这样做的(或者曾经这样做过)。


仅当您将字符串作为参数传递给 header() 包含换行符,后面不跟空格或制表符(这将在下一行继续标题) 。

现在, setcookie() 实际上会urlencode() 其值 (< a href="http://us.php.net/manual/en/function.setrawcookie.php" rel="nofollow noreferrer">setrawcookie() 不会),所以换行不会导致错误。

trim() 函数,另一方面,只会从其参数的开头和结尾去除空格,并保持任何其他换行字符不变。所以也许你可以尝试类似 preg_replace('/\s+ /', '') 代替。

为什么 setcookie() 方法不对我来说,这对你不起作用并不是显而易见的。可能是您实际上看到了 cookie(使用 setcookie() 设置),但不希望其中出现 url 转义,并且在代码中的某个地方默默地拒绝它。

但是,这并不能解释为什么你的第一个 header()似乎可以工作(其中有换行符);似乎您的某些 cookie 值中有换行符,而有些则没有。

顺便说一句,如果您希望子域看到 cookie,则将域设置为“.local”(以“.”开头)是正确的做法。

关于使用 setcookie()< 设置 cookie 的一些额外注意事项/a> 在 PHP 文档(尤其是用户注释)中进行了讨论。

EDIT:
I've now had a look at RFC2109, 4.3.2 Rejecting Cookies:

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

    ...

  • A Set-Cookie with Domain=.com or Domain=.com., will always be
    rejected, because there is no embedded dot.

It seems that the browser is rejecting '.local' due to security concerns. To set a cookie for a domain, it must have at least two dots (e.g. '.cookiedomain.local').

Setting a cookie from one subdomain (e.g. one.local) for another subdomain (e.g. another.local) isn't possible AFAIK. What you can do to overcome this problem is redirecting the user to a cookie domain that sets/gets all cookies and redirects the user again to where they came from with the cookie data included in the url as query parameters. Microsoft does (or did) it like this for its own domains (msn.com, microsoft.com).


The error that you get ("Header may not contain...") is only triggered if the string you pass as an argument to header() contains a linefeed character that is not followed by either a space or a tab (which would continue the header on the next line).

Now, setcookie() will actually urlencode() its value (setrawcookie() will not), so a linefeed will not cause an error there.

The trim() function, on the other hand, will strip whitespace only from the beginning and end of its argument and leave any other linefeed characters intact. So perhaps you could try something like preg_replace('/\s+/', '') instead.

Why the setcookie() approach doesn't work for you isn't immidiately obvious to me. Could be that you are actually seeing the cookie (set with setcookie()) but aren't expecting url escapes in it, and are silently rejecting it somewhere in your code.

However, that doesn't explain why your first header() seems to work (with linefeeds in it); it seems that some of your cookie values have linefeeds in them and some do not.

Setting the domain to '.local' (leading '.') is the right thing to do, by the way, if you want subdomains to see the cookie.

Some additional caveats about setting cookies with setcookie() are discussed in the PHP documentation (especially user comments).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文