如何在 CakePHP 2.3 中设置 samesite cookie 属性?

How can I set the samesite cookie attribute in CakePHP 2.3?

CakePHP 2.3 在 core.php 文件中设置 Session 变量(包括 cookie 属性)。我需要为会话 cookie 设置 samesite=NoneSecure=true,但在配置中似乎没有这些设置可用,它仅显示以下选项:

我现在是这样的:

Configure::write('Session', array(
                                    'defaults' => 'database',
                                    'handler' => array('model' => 'cake_sessions'),
                                    'timeout' => 60
                                    ));

有解决办法吗?我一直在研究如何使用 php 来做到这一点,但我不确定我将如何编辑 CakePHP 使用我想要的属性创建的会话 cookie,或者一旦 cookie 是否可行已创建。

之前 PHP 7.3

在 PHP 早于 PHP 7.3 的版本中,您可以通过利用 cookie 路径 hack 注入 SameSite 属性,其中包括将更多 cookie 属性附加到路径,通过只需用分号关闭路径。

只需相应地在 app/Config/core.php 中配置 session.cookie_path ini 选项,例如,如果您的应用程序的基本路径是 /:

Configure::write('Session', [
    'defaults' => 'php',
    'ini' => [
        'session.cookie_path' => '/; SameSite=None',
    ],
]);

当您通过 https 访问您的站点时,Secure 属性(即 session.cookie_secure ini 选项)将由 CakePHP 自动配置。

截至 PHP 7.3

从 PHP 7.3 开始的 PHP 版本中,您将使用 session.cookie_samesite ini 选项代替:

Configure::write('Session', [
    'defaults' => 'php',
    'ini' => [
        'session.cookie_samesite' => 'None',
    ],
]);

其他饼干

所有这些当然只适用于会话 cookie,如果您通过 the Cookie component 使用其他 cookie,那么您也必须通过修改 $path 属性 因此,与会话不同,您必须明确启用安全 cookie:

$this->Cookie->path = '/; SameSite=None';
$this->Cookie->secure = true;

对于 PHP 7.3+,您必须使用 custom/extended cookie 组件和 extended/custom response class where you'd override the CookieComponent::_write(), CakeResponse::cookie() and CakeResponse::_setCookies() methods accordingly, so that the component allows to set an option for same site, and the response will pass it over to the setcookie() 调用。

示例:

<?php
// in app/Controller/Component/AppCookieComponent.php

App::uses('CookieComponent', 'Controller/Component');

class AppCookieComponent extends CookieComponent
{
    public $sameSite = 'Lax';

    protected function _write($name, $value)
    {
        $this->_response->cookie(array(
            'name' => $this->name . $name,
            'value' => $this->_encrypt($value),
            'expire' => $this->_expires,
            'path' => $this->path,
            'domain' => $this->domain,
            'secure' => $this->secure,
            'httpOnly' => $this->httpOnly,
            'sameSite' => $this->sameSite,
        ));

        if (!empty($this->_reset)) {
            $this->_expires = $this->_reset;
            $this->_reset = null;
        }
    }
}
<?php
// in app/Network/AppResponse.php

App::uses('CakeResponse', 'Network');

class AppResponse extends CakeResponse
{
    public function cookie($options = null)
    {
        $options += [
            'sameSite' => 'Lax',
        ];

        return parent::cookie($options);
    }

    protected function _setCookies()
    {
        foreach ($this->_cookies as $name => $cookie) {
            $options = [
                'expires' => $cookie['expire'],
                'path' => $cookie['path'],
                'domain' => $cookie['domain'],
                'secure' => $cookie['secure'],
                'httponly' => $cookie['httpOnly'],
                'samesite' => $cookie['sameSite'],
            ];
            setcookie($name, $cookie['value'], $options);
        }
    }
}

在前端控制器中注入自定义响应:

// in app/webroot/index.php

App::uses('Network', 'AppResponse');

$Dispatcher = new Dispatcher();
$Dispatcher->dispatch(
    new CakeRequest(),
    new AppResponse()
);

Alias the Cookie component 与自定义组件 class:

// in app/Controller/AppController.php

public $components = [
    'Cookie' => [
        'className' => 'AppCookie',
    ],
];

然后在使用之前相应地配置组件:

$this->Cookie->sameSite = 'None';
$this->Cookie->secure = true;

或直接使用响应对象来设置您的 cookie:

$this->response->cookie([
    'name' => 'cookie name',
    'value' => 'cookie value',
    'expire' => time() + (60 * 24),
    'path' => '/',
    'domain' => '',
    'secure' => true,
    'httpOnly' => false,
    'sameSite' => 'None',
]);