summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Andreev <narf@devilix.net>2022-01-05 16:52:40 +0100
committerGitHub <noreply@github.com>2022-01-05 16:52:40 +0100
commitc382445b71682cfa4ee9048a5b775d07102d0ef8 (patch)
tree72f742fa278de276601724ca413dc773eaa67239
parent5e79f1b0dda522efcd1a0cb379d6e7fb1f5cc557 (diff)
parent1415d4ec99c7dbaec2c34742536e00eb9cb7493f (diff)
Merge pull request #6025 from gxgpet/develop
SameSite attribute implementation for CI_Input::set_cookie
-rw-r--r--application/config/config.php2
-rw-r--r--system/core/Input.php42
-rw-r--r--user_guide_src/source/libraries/input.rst21
3 files changed, 53 insertions, 12 deletions
diff --git a/application/config/config.php b/application/config/config.php
index f92d11f5d..596f8fefe 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -385,6 +385,7 @@ $config['sess_regenerate_destroy'] = FALSE;
| 'cookie_path' = Typically will be a forward slash
| 'cookie_secure' = Cookie will only be set if a secure HTTPS connection exists.
| 'cookie_httponly' = Cookie will only be accessible via HTTP(S) (no javascript)
+| 'cookie_samesite' = Cookie's samesite attribute (Lax, Strict or None)
|
| Note: These settings (with the exception of 'cookie_prefix' and
| 'cookie_httponly') will also affect sessions.
@@ -395,6 +396,7 @@ $config['cookie_domain'] = '';
$config['cookie_path'] = '/';
$config['cookie_secure'] = FALSE;
$config['cookie_httponly'] = FALSE;
+$config['cookie_samesite'] = 'Lax';
/*
|--------------------------------------------------------------------------
diff --git a/system/core/Input.php b/system/core/Input.php
index 87e6cfed9..71f28221f 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -300,14 +300,15 @@ class CI_Input {
* @param string $prefix Cookie name prefix
* @param bool $secure Whether to only transfer cookies via SSL
* @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript)
+ * @param string $samesite SameSite attribute
* @return void
*/
- public function set_cookie($name, $value = '', $expire = 0, $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL)
+ public function set_cookie($name, $value = '', $expire = 0, $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL, $samesite = NULL)
{
if (is_array($name))
{
// always leave 'name' in last place, as the loop will break otherwise, due to $$item
- foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'httponly', 'name') as $item)
+ foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'httponly', 'name', 'samesite') as $item)
{
if (isset($name[$item]))
{
@@ -348,7 +349,42 @@ class CI_Input {
$expire = ($expire > 0) ? time() + $expire : 0;
}
- setcookie($prefix.$name, $value, $expire, $path, $domain, $secure, $httponly);
+ isset($samesite) OR $samesite = config_item('cookie_samesite');
+ if (isset($samesite))
+ {
+ $samesite = ucfirst(strtolower($samesite));
+ in_array($samesite, array('Lax', 'Strict', 'None'), TRUE) OR $samesite = 'Lax';
+ }
+ else
+ {
+ $samesite = 'Lax';
+ }
+
+ if ($samesite === 'None' && ! $secure)
+ {
+ log_message('error', $name.' cookie sent with SameSite=None, but without Secure attribute.');
+ }
+
+ if (is_php('7.3'))
+ {
+ $setcookie_options = array(
+ 'expires' => $expire,
+ 'path' => $path,
+ 'domain' => $domain,
+ 'secure' => $secure,
+ 'httponly' => $httponly,
+ 'samesite' => $samesite,
+ );
+ setcookie($prefix.$name, $value, $setcookie_options);
+ }
+ else
+ {
+ $cookie_header = 'Set-Cookie: '.$prefix.$name.'='.rawurlencode($value);
+ $cookie_header .= ($expire === 0 ? '' : '; expires='.gmdate('D, d-M-Y H:i:s T', $expire));
+ $cookie_header .= '; path='.$path.($domain !== '' ? '; domain='.$domain : '');
+ $cookie_header .= ($secure ? '; secure' : '').($httponly ? '; HttpOnly' : '').'; SameSite='.$samesite;
+ header($cookie_header);
+ }
}
// --------------------------------------------------------------------
diff --git a/user_guide_src/source/libraries/input.rst b/user_guide_src/source/libraries/input.rst
index 730b3a9b0..e0f3d8417 100644
--- a/user_guide_src/source/libraries/input.rst
+++ b/user_guide_src/source/libraries/input.rst
@@ -242,7 +242,7 @@ Class Reference
This method is identical to ``get()``, ``post()`` and ``cookie()``,
only it fetches the *php://input* stream data.
- .. php:method:: set_cookie($name = ''[, $value = ''[, $expire = 0[, $domain = ''[, $path = '/'[, $prefix = ''[, $secure = NULL[, $httponly = NULL]]]]]]])
+ .. php:method:: set_cookie($name = ''[, $value = ''[, $expire = 0[, $domain = ''[, $path = '/'[, $prefix = ''[, $secure = NULL[, $httponly = NULL[, $samesite = NULL]]]]]]]])
:param mixed $name: Cookie name or an array of parameters
:param string $value: Cookie value
@@ -252,6 +252,7 @@ Class Reference
:param string $prefix: Cookie name prefix
:param bool $secure: Whether to only transfer the cookie through HTTPS
:param bool $httponly: Whether to only make the cookie accessible for HTTP requests (no JavaScript)
+ :param string $samesite: SameSite attribute ('Lax', 'Strict', 'None')
:rtype: void
@@ -265,13 +266,14 @@ Class Reference
parameter::
$cookie = array(
- 'name' => 'The Cookie Name',
- 'value' => 'The Value',
- 'expire' => 86500,
- 'domain' => '.some-domain.com',
- 'path' => '/',
- 'prefix' => 'myprefix_',
- 'secure' => TRUE
+ 'name' => 'The Cookie Name',
+ 'value' => 'The Value',
+ 'expire' => 86500,
+ 'domain' => '.some-domain.com',
+ 'path' => '/',
+ 'prefix' => 'myprefix_',
+ 'secure' => TRUE,
+ 'samesite' => 'Strict'
);
$this->input->set_cookie($cookie);
@@ -297,13 +299,14 @@ Class Reference
The *httponly* and *secure* flags, when omitted, will default to your
``$config['cookie_httponly']`` and ``$config['cookie_secure']`` settings.
+ The *samesite* parameter can be ``'Lax'``, ``'Strict'`` or ``'None'``. If not set, the same-site cookie attribute will default to ``'Lax'``.
**Discrete Parameters**
If you prefer, you can set the cookie by passing data using individual
parameters::
- $this->input->set_cookie($name, $value, $expire, $domain, $path, $prefix, $secure);
+ $this->input->set_cookie($name, $value, $expire, $domain, $path, $prefix, $secure, $samesite);
.. php:method:: ip_address()