如何告诉PHP使用SameSite=None作为跨站点cookie?

fsi0uk1n  于 2023-05-16  发布在  PHP
关注(0)|答案(7)|浏览(449)

根据https://php.watch/articles/PHP-Samesite-cookieshttps://www.php.net/manual/en/session.security.ini.php上的PHP文档,这个新功能只有2个可能的配置选项,在PHP 7.3中添加:

  1. session.cookie_samesite=Lax
  2. session.cookie_samesite=严格
    然而,根据Chrome控制台,这需要设置为“无”:
    与URL处的跨站点资源关联的cookie设置时没有SameSite属性。它已被阻止,因为Chrome现在仅在跨站点请求设置为SameSite=NoneSecure时才提供cookie。您可以在应用程序>存储> Cookie下的开发人员工具中查看Cookie,并在URL和URL中查看更多详细信息。
    因此,我无法再设置跨站点cookie。解决方法是什么?
idv4meu8

idv4meu81#

您可以使用ini_set将该值设置为“None”。在使用该函数时,不检查该值是否受支持:

ini_set('session.cookie_samesite', 'None');
session_start();

session_set_cookie_params也可以设置为:

session_set_cookie_params(['samesite' => 'None']);
session_start();

在php.ini中支持的bug报告是here
正如@shrimpwagon在下面的评论中所说,session.cookie_secure必须是true才能工作。PHP不需要它,但浏览器需要。

lvmkulzt

lvmkulzt2#

ini_set('session.cookie_secure', "1"); ini_set('session.cookie_httponly', "1"); ini_set('session.cookie_samesite','None'); session_start();
php 7.4在phpinfo

中的相同站点
页面不存在页面不存在.

$currentCookieParams = session_get_cookie_params();
$cookie_domain= 'your domain';
if (PHP_VERSION_ID >= 70300) {
session_set_cookie_params([
    'lifetime' =>  $currentCookieParams["lifetime"],
    'path' => '/',
    'domain' => $cookie_domain,
    'secure' => "1",
    'httponly' => "1",
    'samesite' => 'None',
]);
} else {
session_set_cookie_params(
    $currentCookieParams["lifetime"],
    '/; samesite=None',
    $cookie_domain,
    "1",
    "1"
);
}
session_start();
8ljdwjyq

8ljdwjyq3#

不良:

session.cookie_samesite=None

正确:

session.cookie_samesite="None"

说明here

wwtsj6pe

wwtsj6pe4#

这种方法可以帮助我们
Secure + SameSite=None下面的nginx上添加header的属性
位置/ {
代理_cookie_path /“/; sameSite=none”;
}
它对我起作用了!

7jmck4yq

7jmck4yq5#

对于PHP 5.6.40,有一个解决方法(hack on path参数),它不涉及重新构建PHP。
如果您在重建PHP二进制文件时没有问题,我设法将此功能从PHP 7.3移植到PHP 5.6.40,现在有一个pull请求。我需要它来完成尚未迁移的项目。我知道5.6分支已经过时了,我只是分享一下。
拉取请求:https://github.com/php/php-src/pull/6446
我们的repo与更改:https://github.com/Inducido/php-src/tree/PHP-5.6.40
在Debian 8.11上测试

新增功能

Session:.为setcookie()、setrawcookie()和session_set_cookie_params()添加了对SameSite cookie指令的支持。从PHP 7.x分支的端口,它们都在最后有一个“samesite”附加参数(字符串)
原型:

bool setcookie(string name [, string value [, int expires [, string path [, string domain [, bool secure[, bool httponly[, string samesite]]]]]]])
bool setrawcookie(string name [, string value [, int expires [, string path [, string domain [, bool secure[, bool httponly[, string samesite]]]]]]])
void session_set_cookie_params(int lifetime [, string path [, string domain [, bool secure[, bool httponly[, string samesite]]]]])
(session_get_cookie_params updated too)

INI文件处理的变化

  • 会话.cookie_samesite .新的INI选项允许设置Cookie的SameSite指令。默认值为“”(空字符串),因此不设置SameSite指令。可以设置为“Lax”或“Strict”,或设置相应SameSite指令的“None”。当使用“None”时,请确保包含引号,因为none的解释与ini文件中的false类似。

这解决了Chrome中“由于用户偏好设置,此设置Cookie被阻止”的问题。

vh0rcniy

vh0rcniy6#

如果您使用nginx,您也可以使用lua修改cookie。这是一个有点黑客,但我发现它是工作良好的遗留网站:

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
            include snippets/fastcgi-php.conf;

            fastcgi_pass unix:/run/php/php5.6-fpm.sock;

            # This is the relevant part:
            header_filter_by_lua '
                    local cookies = ngx.header.set_cookie
                    if cookies then
                            if type(cookies) ~= "table" then
                                    cookies = {cookies}
                            end
                            local gsub = string.gsub
                            local changed
                            for i, cookie in ipairs(cookies) do
                                    local new_cookie = gsub(cookie, "^PHPSESSION=(.*)", "PHPSESSION=%1; Samesite=strict", 1)
                                    if new_cookie ~= cookie then
                                            cookies[i] = new_cookie
                                            changed = true
                                    end
                            end
                            if changed then
                                    ngx.header.set_cookie = cookies
                            end
                    end
            ';
            # End Lua
    }

您可能需要调整正则表达式(gsub),但我发现它工作得很好。

6tqwzwtp

6tqwzwtp7#

使命:让JS AJAX 请求从另一个域完成(例如:localhost)
步骤:
A.在 AJAX 请求中添加withCredentials
B.在其余的Access-Control-Allow-...头中设置Access-Control-Allow-Credentials: true
C.将"samesite" => "none"添加到您的会话cookie参数。
最后,我的代码看起来像这样:
服务器:

$currentCookieParams = session_get_cookie_params();
session_set_cookie_params([
    "lifetime" => $currentCookieParams["lifetime"],
    "path" => $currentCookieParams["path"],
    "domain" => $_SERVER["HTTP_HOST"],
    "secure" => true,
    "samesite" => "none",
    "httponly" => $currentCookieParams["httponly"]
]);
header("Access-Control-Allow-Origin: " . $_SERVER["HTTP_ORIGIN"]);
header("Access-Control-Allow-Headers: " . $_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"]);
header("Access-Control-Allow-Methods: " . $_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"]);
header('Access-Control-Max-Age: 1000');
header('Access-Control-Allow-Credentials: true');

js -客户端:

fetch(`https://example.com/login.php`, {
    method: 'POST',
    withCredentials: true,
    body: `username=${user}&password=${pass}`
 }).then(res => {
     if (res.status === 200) {



        //here session cookie exists and sent to server, so i can access the data
        fetch(`https://example.com/secret.php`, {
            method: 'GET',
            withCredentials: true,
        }).then(res => {
            if (res.status === 200) {
                console.log(res.body);
            } else {
                console.error("error")
            }
        }).catch(err => {
            console.log(err)
        })


    } else {
        console.error("error")
    }
}).catch(err => {
    console.log(err)
})

在ubuntu上测试了FF 112和Chromium 113

相关问题