PHP setcookie“SameSite=Strict”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39750906/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 01:59:33  来源:igfitidea点击:

PHP setcookie "SameSite=Strict"?

phpsecuritycookies

提问by Lauro Moraes

I recently read "RFC 6265" on the attribute "Same Site", I looked at some articles that talked about that in April 2016, "same-site" attribute has been implemented for Chrome 51 and Opera 39 ...

我最近阅读了“相同站点”属性上的“RFC 6265”,我查看了一些在 2016 年 4 月谈到的文章,“相同站点”属性已为 Chrome 51 和 Opera 39 实现......

I wonder if current PHP supports creating cookies with this attribute?

我想知道当前的 PHP 是否支持使用此属性创建 cookie?

Reference:

参考:

采纳答案by Steffen

[Important update:As @caw pointed out below, this hack WILL BREAK in PHP 7.3. Stop using it now to save yourself from unpleasant surprises! Or at least wrap it in a PHP version check like if (PHP_VERSION_ID < 70300) { ... } else { ... }.]

[重要更新:正如@caw 在下面指出的那样,这个 hack将在 PHP 7.3 中中断。立即停止使用它,以免您遇到令人不快的意外!或者至少将其包装在 PHP 版本检查中,例如if (PHP_VERSION_ID < 70300) { ... } else { ... }.]

It seems like you can abuse the "path" or "domain" parameter of PHP's "setcookie" function to sneak in the SameSite attribute because PHP does not escape semicolons:

似乎您可以滥用 PHP 的“setcookie”函数的“path”或“domain”参数来潜入 SameSite 属性,因为 PHP 不会转义分号:

setcookie('samesite-test', '1', 0, '/; samesite=strict');

Then PHP sends the following HTTP header:

然后 PHP 发送以下 HTTP 标头:

Set-Cookie: samesite-test=1; path=/; samesite=strict

设置-Cookie:samesite-test=1;路径=/;同站点=严格

I've just discovered this a few minutes ago, so please do your own testing! I'm using PHP 7.1.11.

几分钟前我刚刚发现了这一点,所以请自行测试!我使用的是 PHP 7.1.11。

回答by Marty Aghajanyan

1. For PHP >= v7.3

1. 对于 PHP >= v7.3

You can use the $optionsarray to set the samesitevalue, for example:

您可以使用$options数组来设置samesite值,例如:

setcookie($name, $value, [
    'expires' => time() + 86400,
    'path' => '/',
    'domain' => 'domain.com',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'None',
]);

The value of the samesite element should be either None, Laxor Strict.

samesite 元素的值应该是None,LaxStrict

Read more in the manual page.

手册页中阅读更多内容。

2. For PHP < v7.3

2. 对于 PHP < v7.3

You can use one of the following solutions/workarounds depending on your codebase/needs

您可以根据您的代码库/需求使用以下解决方案/解决方法之一

2.1 Setting SameSite cookies using Apache configuration

2.1 使用 Apache 配置设置 SameSite cookie

You can add the following line to your Apache configuration

您可以将以下行添加到您的 Apache 配置中

Header always edit Set-Cookie (.*) "; SameSite=Lax"

and this will update all your cookies with SameSite=Laxflag

这将使用SameSite=Lax标志更新您的所有 cookie

See more here: https://blog.giantgeek.com/?p=1872

在此处查看更多信息:https: //blog.giantgeek.com/?p=1872

2.2 Setting SameSite cookies using Nginx configuration

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";
}

Same here, this also will update all your cookies with SameSite=Laxflag

同样在这里,这也将使用SameSite=Lax标志更新您的所有 cookie

See more here: https://serverfault.com/questions/849888/add-samesite-to-cookies-using-nginx-as-reverse-proxy

在此处查看更多信息:https: //serverfault.com/questions/849888/add-samesite-to-cookies-using-nginx-as-reverse-proxy

2.3 Setting SameSite cookies using headermethod

2.3 使用header方法设置SameSite cookie

As we know cookies are just a header in HTTP request with the following structure

我们知道 cookie 只是 HTTP 请求中的一个标头,具有以下结构

Set-Cookie: key=value; path=/; domain=example.org; HttpOnly; SameSite=Lax

so we can just set the cookies with headermethod

所以我们可以用header方法设置cookies

header("Set-Cookie: key=value; path=/; domain=example.org; HttpOnly; SameSite=Lax");

In fact, Symfony is not waiting for PHP 7.3 and already doing it under the hood, see here

事实上,Symfony 并没有等待 PHP 7.3 并且已经在幕后做了,请看这里

You can use same in Laravel too because Laravel under the hood using Symfony's Symfony\Component\HttpFoundation\Cookieclass

您也可以在 Laravel 中使用相同的内容,因为 Laravel 在后台使用 Symfony 的Symfony\Component\HttpFoundation\Cookie

2.4 Setting SameSite cookies using a bug in setcookiemethod

2.4 使用setcookie方法中的错误设置 SameSite cookie

setcookie('cookie-name', '1', 0, '/; samesite=strict');

Be careful with this one, it's a known bug in PHP setcookiemethod and already resolved in PHP7.3 version, see here - https://github.com/php/php-src/commit/5cb825df7251aeb28b297f071c35b227a3949f01

小心这个,这是 PHPsetcookie方法中的一个已知错误,已经在 PHP7.3 版本中解决,请参见此处 - https://github.com/php/php-src/commit/5cb825df7251aeb28b297f071c35b227a3949f01

回答by jlyon

Based on Steffen's answer above, this is the method I am using to support both php <= 7.2 and php >= 7.3:

根据上面Steffen 的回答,这是我用来支持 php <= 7.2 和 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://stackoverflow.com/a/46971326/2308553 
 *
 * @param [type] $name
 * @param [type] $value
 * @param [type] $expire
 * @param [type] $path
 * @param [type] $domain
 * @param [type] $secure
 * @param [type] $httponly
 * @return void
 */
function setcookieSameSite($name, $value, $expire, $path, $domain, $secure, $httponly)
{
    if (PHP_VERSION_ID < 70300) {
        setcookie($name, $value, $expire, "$path; samesite=None", $domain, $secure, $httponly);
    }
    else {
        setcookie($name, $value, [
            'expires' => $expire,
            'path' => $path,
            'domain' => $domain,
            'samesite' => 'None',
            'secure' => $secure,
            'httponly' => $httponly,
        ]);
    }
}

回答by David Komanek

According to this site, it seems it is a matter of PHP 7.3. As of the voting results, a more general extension to cookie-related functions is being implemented + there might be also a new key in php.ini file.

根据此站点,似乎是 PHP 7.3 的问题。根据投票结果,正在实现对 cookie 相关功能的更通用扩展 + php.ini 文件中可能还有一个新键。

But as Marc B already wrote, you can use header() function call instead, I would do it in some file with used for inclusion of other initial stuff.

但是正如 Marc B 已经写的那样,您可以改用 header() 函数调用,我会在某个文件中使用用于包含其他初始内容的文件。

回答by jetblack

I wrote a class for setting samesite cookies.

我写了一个用于设置相同站点 cookie 的类。

https://github.com/ovunctukenmez/SameSiteCookieSetter

https://github.com/ovunctukenmez/SameSiteCookieSetter

It works on all PHP versions. It also checks if the browser supports samesite parameter properly.

它适用于所有 PHP 版本。它还检查浏览器是否正确支持 samesite 参数。

Here is the usage:

这是用法:

//set samesite strict php cookie
SameSiteCookieSetter::setcookie('samesite_test','testvalue', array('samesite' => 'Strict'));

回答by Y.K.

Worth mentioning that Safari 12 on both macOS and iOS will not recognise a value of None for the SameSite attribute, and default to a value of Strict.

值得一提的是,macOS 和 iOS 上的 Safari 12 都无法识别 SameSite 属性的 None 值,并默认为 Strict 值。

Version 13 will accept "None", but without explicitly setting a value, it defaults to "Lax".

版本 13 将接受“None”,但没有明确设置值,默认为“Lax”。

Here's a good explanation:

这是一个很好的解释:

https://www.thinktecture.com/en/identity/samesite/samesite-in-a-nutshell/

https://www.thinktecture.com/en/identity/samesite/samesite-in-a-nutshell/

回答by Andrew Koster

There are a lot of examples showing how to set this attribute, but not many explanations of why.

有很多例子展示了如何设置这个属性,但没有太多解释为什么。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_attribute

https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_attribute

If a cookie is needed to be sent cross-origin, opt out of the SameSite restriction by using the None directive. The None directive requires that the Secure attribute also be used.

如果需要跨源发送 cookie,请使用 None 指令选择退出 SameSite 限制。None 指令要求还使用 Secure 属性。

The examples that are setting SameSiteto Noneor Laxare only appropriate for cross-domain scenarios. If your code isn't cross-domain, use Strict.

设置SameSiteNoneLax仅适用于跨域场景的示例。如果您的代码不是跨域的,请使用Strict.

回答by Ethan Burnside

Adding to the answer by Marty Aghajanyan (because apparently I can answer, but not yet comment)

添加 Marty Aghajanyan 的答案(因为显然我可以回答,但尚未发表评论)

Doing it in Apache via mod_headers in conjunction with PHP was not working for me in Apache 2.4.29 (Ubuntu). In reviewing the docs (http://www.balkangreenfoundation.org/manual/en/mod/mod_headers.html) I noticed the "always" condition has certain situations where it does not work from the same pool of response headers. Thus the following worked for me to set the SameSite parameter. (Tho in my case I am setting None for the recent Chrome 80 update)

在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 ^(.*)$ "; Secure; SameSite=None"

The docs also suggest that if you want to cover all your bases you could add the directive both with and without "always", but I have not tested that.

文档还建议,如果您想涵盖所有基础,您可以在有和没有“始终”的情况下添加指令,但我还没有测试过。