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

余生长醉 提交于 2020-12-15 06:38:17

问题


CakePHP 2.3 sets the Session variables (including cookie attributes) in the core.php file. I need to set samesite=None and Secure=true for the session cookie, but it doesn't appear to have those settings available in the configuration, which shows only the following options:

  • Session.cookie - The name of the cookie to use. Defaults to 'CAKEPHP'
  • Session.timeout - The number of minutes you want sessions to live for. This timeout is handled by CakePHP
  • Session.cookieTimeout - The number of minutes you want session cookies to live for.
  • Session.checkAgent - Do you want the user agent to be checked when starting sessions? You might want to set the value to false, when dealing with older versions of IE, Chrome Frame or certain web-browsing devices and AJAX
  • Session.defaults - The default configuration set to use as a basis for your session. There are four builtins: php, cake, cache, database.
  • Session.handler - Can be used to enable a custom session handler. Expects an array of of callables, that can be used with session_save_handler. Using this option will automatically add session.save_handler to the ini array.
  • Session.autoRegenerate - Enabling this setting, turns on automatic renewal of sessions, and sessionids that change frequently. See CakeSession::$requestCountdown.
  • Session.ini - An associative array of additional ini values to set.

This is how I have it now:

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

Is there a workaround for this? I've been looking at how to do this with php but I'm not sure how I would edit the session cookie that CakePHP creates with the attributes I want, or if that is possible at all once the cookie has been created.


回答1:


Before PHP 7.3

In PHP versions earlier than PHP 7.3, you can inject the SameSite attribute by utilizing the cookie path hack, which consists of appending further cookie attributes to the path, by simply closing the path of with a semicolon.

Simply configure the session.cookie_path ini option in app/Config/core.php accordingly, for example like this in case your application's base path is /:

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

The Secure attribute (ie the session.cookie_secure ini option) will automatically be configured by CakePHP when you're visiting your site via https.

As of PHP 7.3

In PHP versions as of PHP 7.3 you would use the session.cookie_samesite ini option instead:

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

Other cookies

All of this of course only applies to session cookies, if you're using additional cookies via the Cookie component, then you'd have to utilize the path hack there too, by modifying the $path property accordingly, and unlike with sessions, you'd have to explicitly enable secure cookies:

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

With PHP 7.3+ you'd have to use a custom/extended cookie component, and an 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() call.

Example:

<?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;
        }
    }
}
  • https://github.com/cakephp/cakephp/blob/2.3.10/lib/Cake/Controller/Component/CookieComponent.php#L413
  • https://github.com/cakephp/cakephp/blob/2.10.22/lib/Cake/Controller/Component/CookieComponent.php#L393
<?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);
        }
    }
}
  • https://github.com/cakephp/cakephp/blob/2.3.10/lib/Cake/Network/CakeResponse.php#L1189
  • https://github.com/cakephp/cakephp/blob/2.3.10/lib/Cake/Network/CakeResponse.php#L437
  • https://github.com/cakephp/cakephp/blob/2.10.22/lib/Cake/Network/CakeResponse.php#L1236
  • https://github.com/cakephp/cakephp/blob/2.10.22/lib/Cake/Network/CakeResponse.php#L454

Inject the custom response in the front controller:

// in app/webroot/index.php

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

$Dispatcher = new Dispatcher();
$Dispatcher->dispatch(
    new CakeRequest(),
    new AppResponse()
);
  • https://github.com/cakephp/cakephp/blob/2.3.10/app/webroot/index.php#L107-L110
  • https://github.com/cakephp/cakephp/blob/2.10.22/app/webroot/index.php#L114-L118

Alias the Cookie component with the custom component class:

// in app/Controller/AppController.php

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

and then configure the component accordingly before using it:

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

or use the response object directly to set your cookies:

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


来源:https://stackoverflow.com/questions/64884554/how-can-i-set-the-samesite-cookie-attribute-in-cakephp-2-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!