如何在 CakePHP 2.3 中设置 SameSite Cookie 属性?

Alb*_*ert 2 cookies cakephp cakephp-2.3 cakephp-2.x samesite

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

  • Session.cookie- 要使用的 cookie 的名称。默认为“CAKEPHP”
  • Session.timeout- 您希望会话持续的分钟数。这个超时由 CakePHP 处理
  • Session.cookieTimeout- 您希望会话 cookie 存活的分钟数。
  • Session.checkAgent- 您希望在启动会话时检查用户代理吗?在处理旧版本的 IE、Chrome Frame 或某些网络浏览设备和 AJAX 时,您可能需要将该值设置为 false
  • Session.defaults- 用作会话基础的默认配置集。有四个内置函数:php、cake、cache、database。
  • Session.handler- 可用于启用自定义会话处理程序。需要一个可调用数组,可以与session_save_handler. 使用此选项将自动添加session.save_handler到 ini 数组中。
  • Session.autoRegenerate- 启用此设置,打开会话自动更新以及经常更改的sessionid。请参阅 CakeSession::$requestCountdown。
  • Session.ini- 要设置的附加 ini 值的关联数组。

这就是我现在的情况:

Configure::write('Session', array(
                                    'defaults' => 'database',
                                    'handler' => array('model' => 'cake_sessions'),
                                    'timeout' => 60
                                    ));
Run Code Online (Sandbox Code Playgroud)

有解决方法吗?我一直在研究如何使用 php 执行此操作,但我不确定如何编辑 CakePHP 使用我想要的属性创建的会话 cookie,或者在创建 cookie 后是否可以这样做。

ndm*_*ndm 5

PHP 7.3 之前

在 PHP 7.3 之前的 PHP 版本中,您可以SameSite利用 cookie 路径 hack 来注入属性,该方法包括将更多 cookie 属性附加到路径中,只需用分号关闭路径即可。

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

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

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

从 PHP 7.3 开始

在 PHP 7.3 之前的 PHP 版本中,您可以使用session.cookie_samesiteini 选项:

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

其他cookies

当然,所有这些仅适用于会话 cookie,如果您通过Cookie 组件使用其他 cookie ,那么您也必须通过$path相应地修改属性来利用路径 hack,并且与会话不同,您需要必须显式启用安全 cookie:

$this->Cookie->path = '/; SameSite=None';
$this->Cookie->secure = true;
Run Code Online (Sandbox Code Playgroud)

使用 PHP 7.3+,您必须使用自定义/扩展 cookie 组件和扩展/自定义响应类,您可以在其中相应地重写CookieComponent::_write()CakeResponse::cookie()CakeResponse::_setCookies()方法,以便该组件允许为同一站点设置选项,并且响应会将其传递给调用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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
<?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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

// in app/webroot/index.php

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

$Dispatcher = new Dispatcher();
$Dispatcher->dispatch(
    new CakeRequest(),
    new AppResponse()
);
Run Code Online (Sandbox Code Playgroud)

使用自定义组件Cookie为组件命名:

// in app/Controller/AppController.php

public $components = [
    'Cookie' => [
        'className' => 'AppCookie',
    ],
];
Run Code Online (Sandbox Code Playgroud)

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

$this->Cookie->sameSite = 'None';
$this->Cookie->secure = true;
Run Code Online (Sandbox Code Playgroud)

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

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