PHP setcookie“SameSite = Strict”?
Posted
技术标签:
【中文标题】PHP setcookie“SameSite = Strict”?【英文标题】:PHP setcookie "SameSite=Strict"? 【发布时间】:2017-02-06 15:13:48 【问题描述】:我最近阅读了关于“Same Site”属性的“RFC 6265”,我看了一些文章,在 2016 年 4 月谈到,Chrome 51 和 Opera 39 已经实现了“same-site”属性......
不知道现在的php是否支持用这个属性创建cookie?
参考:
Feature documentation on Chrome’schromestatus.com
HTTPbis draft first adopted by Chrome
Latest HTTPbis draft
【问题讨论】:
即使 setcookie 函数没有,您也可以始终只输出您自己的自定义header('Set-Cookie: ...')
@MarcB:没错,别忘了对名称和值进行 URL 编码。
here 是一个公开请求,您可以投票和关注。
这个库可以让你使用 cookie 的属性:github.com/delight-im/PHP-Cookie 最重要的是,它还支持 PHP 的内置会话的这个属性,它会自动设置和使用 cookie。或者,等待 PHP 本地发布该功能。
@caw 使用这个库生成 cookie 并将其写入写入客户端的输出缓冲区,然后类才会获取 cookie 并覆盖它,不管这个过程有多快,它确实不保证不能拦截。对于一个处理类似问题的问题...github.com/delight-im/PHP-Cookie/issues/15 虽然这个问题质疑一个草案到 php 会话指向相同的范例。
【参考方案1】:
1。对于 PHP >= v7.3
您可以使用$options
数组来设置samesite
的值,例如:
setcookie($name, $value, [
'expires' => time() + 86400,
'path' => '/',
'domain' => 'domain.com',
'secure' => true,
'httponly' => true,
'samesite' => 'None',
]);
samesite 元素的值应该是None
、Lax
或Strict
。
在manual page 中了解更多信息。
2。对于 PHP
您可以根据您的代码库/需求使用以下解决方案/解决方法之一
2.1 使用 Apache 配置设置 SameSite cookie
您可以将以下行添加到您的 Apache 配置中
Header always edit Set-Cookie (.*) "$1; SameSite=Lax"
这将使用SameSite=Lax
标志更新您的所有cookie
在此处查看更多信息:https://blog.giantgeek.com/?p=1872
2.2 使用 nginx 配置设置 SameSite cookie
location /
# your usual config ...
# hack, set all cookies to secure, httponly and samesite (strict or lax)
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
这里也一样,这也会用SameSite=Lax
标志更新你的所有cookie
在此处查看更多信息:https://serverfault.com/questions/849888/add-samesite-to-cookies-using-nginx-as-reverse-proxy
2.3 使用header
方法设置SameSite cookie
众所周知,cookie 只是 HTTP 请求中的一个标头,具有以下结构
Set-Cookie: key=value; path=/; domain=example.org; HttpOnly; SameSite=Lax
所以我们可以使用 header
方法设置 cookie
header("Set-Cookie: key=value; path=/; domain=example.org; HttpOnly; SameSite=Lax");
事实上,Symfony 并没有等待 PHP 7.3,而是已经在后台做了,see here
?你也可以在 Laravel 中使用它,因为 Laravel 在底层使用 Symfony 的 Symfony\Component\HttpFoundation\Cookie
类
2.4 使用 setcookie
方法中的错误设置 SameSite cookie
setcookie('cookie-name', '1', 0, '/; samesite=strict');
小心这个,这是 PHP setcookie
方法中的一个已知错误,已经在 PHP7.3 版本中解决,请参见此处 - https://github.com/php/php-src/commit/5cb825df7251aeb28b297f071c35b227a3949f01
【讨论】:
看起来这不是 PHP 7.3+ 中setcookie
(和setrawcookie
)的正确方法签名,一组选项作为第三个参数传递,其中一个被调用samesite
。见github.com/php/php-src/blob/PHP-7.3/UPGRADING#L350
PHP 手册指出 samesite
作为数组的一部分在 setcookie
第三个参数中传递,如下所示:php.net/manual/en/function.setcookie.php
@Jarom 实际上,答复者发布的关于setcookie
的 RFC 链接在底部 勘误表 下说:“实际实现的函数替代签名已从原始 RFC。有关详细信息,请参阅 PHP 手册中的文档。查看手册没有提到相同的论点。相反,手册仅将其作为 $options 数组的值提及。有人可以确认 samesite 论点是否真的有效吗?
PHP session_set_cookie_params() 是否也允许将相同站点注入 $path?
@marcovtwout 是的,session_set_cookie_params()
中的注入在 PHP 7.2.24 中也以同样的方式为我工作,我在 PHP 更改日志中没有找到解决此问题的方法,这对我:)【参考方案2】:
[重要更新:正如@caw 在下面指出的,这个黑客WILL BREAK in PHP 7.3。现在停止使用它来避免令人不快的惊喜!或者至少将其包装在 PHP 版本检查中,例如 if (PHP_VERSION_ID < 70300) ... else ...
。]
您似乎可以滥用 PHP 的“setcookie”函数的“路径”或“域”参数来潜入 SameSite 属性,因为 PHP 不会转义分号:
setcookie('samesite-test', '1', 0, '/; samesite=strict');
然后 PHP 发送以下 HTTP 标头:
设置 Cookie:samesite-test=1;路径=/;同站点=严格
我在几分钟前才发现这一点,所以请自己进行测试!我正在使用 PHP 7.1.11。
【讨论】:
我发现这个答案很有趣,我承认我从未尝试过这个,因为规范没有说明(据我所知)这种可能性......我将对此进行测试以查看它的行为 我已经在phptester 在 PHP 7.0 上进行了测试,这个测试是成功的...非常感谢您的回复! 在 Chrome 63(桌面)62 (android)、原生 Android (v62) 和 Opera (48) 上工作... Firefox (57) 不支持,但下一个版本 (58) 承诺支持。跨度> 优秀的 hack - 只要它不破坏,希望它不会破坏。但是您必须关注未来的 PHP 版本,以了解对此函数的更改。在最好的情况下,这一直有效,直到 PHP 发布了直接支持该功能的更新的setcookie
方法,这可能是 PHP 7.3,可以在另一个答案中阅读。
看起来这可能很快就会停止工作(可能在 PHP 7.3 中):github.com/php/php-src/commit/…【参考方案3】:
基于Steffen's answer above,这是我用来支持 php = 7.3 的方法:
/**
* Support samesite cookie flag in both php 7.2 (current production) and php >= 7.3 (when we get there)
* From: https://github.com/GoogleChromeLabs/samesite-examples/blob/master/php.md and https://***.com/a/46971326/2308553
*
* @see https://www.php.net/manual/en/function.setcookie.php
*
* @param string $name
* @param string $value
* @param int $expire
* @param string $path
* @param string $domain
* @param bool $secure
* @param bool $httponly
* @param string $samesite
* @return void
*/
function setCookieSameSite(
string $name, string $value,
int $expire, string $path, string $domain,
bool $secure, bool $httponly, string $samesite = 'None'
): void
if (PHP_VERSION_ID < 70300)
setcookie($name, $value, $expire, $path . '; samesite=' . $samesite, $domain, $secure, $httponly);
return;
setcookie($name, $value, [
'expires' => $expire,
'path' => $path,
'domain' => $domain,
'samesite' => $samesite,
'secure' => $secure,
'httponly' => $httponly,
]);
【讨论】:
感谢您的回答,您能否指出在 Drupal 7 (PHP 7.2.2) 中实现此功能的位置。 替代语法:if (version_compare(phpversion(), '7.3', '<')) ...
.【参考方案4】:
我写了一个类来设置samesite cookie。
https://github.com/ovunctukenmez/SameSiteCookieSetter
它适用于所有 PHP 版本。 它还会检查浏览器是否正确支持 samesite 参数。
这里是用法:
//set samesite strict php cookie
SameSiteCookieSetter::setcookie('samesite_test','testvalue', array('samesite' => 'Strict'));
【讨论】:
我测试了你的代码。对于 PHP 我正在使用你的课程 SameSiteCookieSetter 老版本php有bug,去掉boolval函数才能正常工作【参考方案5】:根据this site,似乎是PHP 7.3 的问题。从投票结果来看,cookie 相关功能的更通用扩展正在实施中 + php.ini 文件中可能还会有一个新键。
但是正如 Marc B 已经写的那样,您可以使用 header() 函数调用来代替,我会在一些用于包含其他初始内容的文件中执行此操作。
【讨论】:
【参考方案6】:添加 Marty Aghajanyan 的答案(因为显然我可以回答,但尚未发表评论)
在 Apache 2.4.29 (Ubuntu) 中,通过 mod_headers 和 PHP 在 Apache 中执行此操作对我不起作用。在查看文档 (http://www.balkangreenfoundation.org/manual/en/mod/mod_headers.html) 时,我注意到“始终”条件在某些情况下无法从同一个响应标头池中工作。因此,以下内容对我有用,可以设置 SameSite 参数。 (就我而言,我为最近的 Chrome 80 更新设置了 None)
Header edit Set-Cookie ^(.*)$ "$1; Secure; SameSite=None"
文档还建议,如果您想涵盖所有基础,您可以添加带有和不带有“always”的指令,但我没有测试过。
【讨论】:
【参考方案7】:值得一提的是,macOS 和 ios 上的 Safari 12 将无法识别 SameSite 属性的 None 值,默认值为 Strict。
版本 13 将接受“None”,但没有明确设置值,它默认为“Lax”。
这里有一个很好的解释:
https://www.thinktecture.com/en/identity/samesite/samesite-in-a-nutshell/
【讨论】:
【参考方案8】:这也可能对仍在苦苦挣扎、使用 PHP >= 7.3.x 和使用 CI 3.1.11 的人有所帮助
在根目录下找到的index.php中,在下面添加一行
if(isset($_COOKIE["PHPSESSID"]))
header('Set-Cookie: PHPSESSID='.$_COOKIE["PHPSESSID"].'; SameSite=None');
它对我有用,在尝试了所有之后(徒劳)
【讨论】:
也为我工作。只需在开始会话时放置它即可。【参考方案9】:有很多例子展示了如何设置这个属性,但没有太多解释为什么。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_attribute
如果需要跨域发送 cookie,请使用 None 指令选择退出 SameSite 限制。 None 指令要求也使用 Secure 属性。
将SameSite
设置为None
或Lax
的示例仅适用于跨域场景。如果您的代码不是跨域的,请使用Strict
。
【讨论】:
以上是关于PHP setcookie“SameSite = Strict”?的主要内容,如果未能解决你的问题,请参考以下文章
PHP:setcookie() 和 unset() 不删除 cookie
unset($_COOKIE['name']) 与 PHP$_ 中的 setcookie
PHP 中内置函数 setcookie() 和 setrawcookie() 的实际实际差异是啥?