PHP 7.3 之前
在 PHP 7.3 之前的 PHP 版本中,您可以通过使用 cookie 路径 hack 注入 SameSite 属性,其中包括将更多 cookie 属性附加到路径,只需用分号关闭路径即可。
只需相应地配置app/Config/core.php 中的session.cookie_path ini 选项,例如,如果您的应用程序的基本路径是/:
Configure::write('Session', [
'defaults' => 'php',
'ini' => [
'session.cookie_path' => '/; SameSite=None',
],
]);
Secure 属性(即session.cookie_secure ini 选项)将在您通过https 访问您的站点时由CakePHP 自动配置。
自 PHP 7.3 起
在 PHP 7.3 以后的 PHP 版本中,您可以使用 session.cookie_samesite ini 选项:
Configure::write('Session', [
'defaults' => 'php',
'ini' => [
'session.cookie_samesite' => 'None',
],
]);
其他 cookie
所有这些当然只适用于会话 cookie,如果您通过 the Cookie component 使用额外的 cookie,那么您也必须通过相应地修改 $path 属性来利用路径破解,而不像对于会话,您必须明确启用安全 cookie:
$this->Cookie->path = '/; SameSite=None';
$this->Cookie->secure = true;
使用 PHP 7.3+,您必须使用自定义/扩展 cookie 组件和扩展/自定义 response class,您可以在其中相应地覆盖 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;
}
}
}
<?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 与自定义组件类:
// in app/Controller/AppController.php
public $components = [
'Cookie' => [
'className' => 'AppCookie',
],
];
然后在使用之前相应地配置组件:
$this->Cookie->sameSite = 'None';
$this->Cookie->secure = true;
或者直接使用响应对象来设置你的cookies:
$this->response->cookie([
'name' => 'cookie name',
'value' => 'cookie value',
'expire' => time() + (60 * 24),
'path' => '/',
'domain' => '',
'secure' => true,
'httpOnly' => false,
'sameSite' => 'None',
]);