I'm configuring the php.ini file, trying to understand the proper syntax for the php.ini file and setting the session-set-cookie.params. First, it's not clear if the settings needs to be in quotes? Can someone please provide an example for proper syntax? My goal is I want to have session variables available across all sub-domains on my website. It also says, "...you need to call session_set_cookie_params() for every request and before session_start() is called." So basically, I need to
<?php
session_set_cookie_params()
session_start()
// PHP CODE HERE
?>
Right? Here's the webpage and php.ini code below what I've figured out thus far.
https://www.php.net/manual/en/function.session-set-cookie-params.php.
session_set_cookie_params(
int $lifetime_or_options,
string|null $path = null,
string|null $domain = null,
bool|null $secure = null,
bool|null $httponly = null
): bool
Here's my config file thus far.
session_set_cookie_params(
600 $lifetime_or_options,
$path = .mywebsite.com,
$domain = /,
$secure = null,
$httponly = null
): bool
It seems to me that you are not attempting to modify php.ini here (php.ini is a static server-wide config file loaded before PHP), but rather set PHP's ini values at runtime via PHP code. To that end, I think you're just misreading the function definition in the documentation a bit, as to how parameters are expressed.
In later versions of PHP (you're using 8 so that counts), it is best to pass the parameters as an array. This is as listed under Alternative signature available as of PHP 7.3.0 in the docs. When the docs mention the value $lifetime_or_options, they mean that parameter can either be an integer lifetime value (600) or an array of all the options as:
Bundle them in an array with []:
session_set_cookie_params([
'lifetime' => 600,
'path' => '/',
'domain' => '.yoursite.example.com',
'secure' => true,
'httponly' => true
]);
Note that I have set secure and httponly to true. httponly will prevent javascript from gaining access to the session cookie, which is appropriate most of the time. However, set secure to false if you need your session to work without SSL - when set true as I have it, the session cookie would only be transmitted over https.
I have also switched your path and domain values.
The other older way to express this is just to pass individual values directly as function parameters - that is the part I think you misunderstood in the docs.
session_set_cookie_params(600, '/', '.yoursite.example.com', true, true);
Note also that 600 is a very short lifetime for a session cookie, only ten minutes. You might need it to live longer.
Related
I'm having a host of issues with PHP's SESSION and I'm not sure what started it all.
I was setting session_start in my code and things were working fine. I added some AJAX functionality then noticed that the session was empty for that particular call. Believing that I was starting the session too late or that maybe I forgot to include it in a page, I removed ALL instances of session_start and put one session_start in my bootstrap. So now my entire code base only has one session_start call and it's the very first line in the application.
This introduced a new issue. Now I am seeing this in dev tools:
Cookie "PHPSESSIONID" does not have a proper “SameSite” attribute value.
Soon, cookies without the “SameSite” attribute or with an invalid
value will be treated as “Lax”. This means that the cookie will no
longer be sent in third-party contexts.
I understand this has to do with SSL but this site doesn't need SSL, and I'm not even sure why I'm getting this warning. Can someone tell me what I need to do to permanently configure my code so I don't have to worry about this warning anymore? Without running SSL of course, because that's not an option.
I'm not even sure why I'm getting this warning.
Me neither :) Btw setcookie documentation is here:
<?php
$arr_cookie_options = array (
'expires' => time() + 60*60*24*30,
'path' => '/',
'domain' => '.example.com', // leading dot for compatibility or use subdomain
'secure' => true, // or false
'httponly' => true, // or false
'samesite' => 'None' // None || Lax || Strict
);
setcookie('TestCookie', 'The Cookie Value', $arr_cookie_options);
?>
Did the warning disappear after you set the samesite option?
According to the article here https://php.watch/articles/PHP-Samesite-cookies and PHP documenation at https://www.php.net/manual/en/session.security.ini.php, There are only 2 possible config options for this new feature, added in PHP 7.3:
session.cookie_samesite=Lax
session.cookie_samesite=Strict
Yet, according to the Chrome console, this needs to be set to "None":
A cookie associated with a cross-site resource at URL was set without the SameSite attribute. It has been blocked, as Chrome now only delivers cookies with cross-site requests if they are set with SameSite=None and Secure. You can review cookies in developer tools under Application>Storage>Cookies and see more details at URL and URL.
Because of this, I can no longer set cross-site cookies. What is the workaround?
You can set the value to "None" using ini_set. There's no check that the value is supported when that function is used:
ini_set('session.cookie_samesite', 'None');
session_start();
session_set_cookie_params can also set it:
session_set_cookie_params(['samesite' => 'None']);
session_start();
The bug report for this to be supported in php.ini is here.
As #shrimpwagon said in a comment below, session.cookie_secure must be true for this to work. PHP doesn't require it, but browsers do.
ini_set('session.cookie_secure', "1"); ini_set('session.cookie_httponly', "1"); ini_set('session.cookie_samesite','None'); session_start();
php 7.4 samesite in phpinfo
php 7.2 samesite does not exist in phpinfo
$currentCookieParams = session_get_cookie_params();
$cookie_domain= 'your domain';
if (PHP_VERSION_ID >= 70300) {
session_set_cookie_params([
'lifetime' => $currentCookieParams["lifetime"],
'path' => '/',
'domain' => $cookie_domain,
'secure' => "1",
'httponly' => "1",
'samesite' => 'None',
]);
} else {
session_set_cookie_params(
$currentCookieParams["lifetime"],
'/; samesite=None',
$cookie_domain,
"1",
"1"
);
}
session_start();
Bad:
session.cookie_samesite=None
Correct:
session.cookie_samesite="None"
Explanation here
This method can be helpful for u
Add header's attributes on nginx below Secure + SameSite=None
location / {
proxy_cookie_path / "/; secure; SameSite=none";
}
It's working on me!
For PHP 5.6.40, there exists a workaround (the hack on path parameter) which does not involve rebuilding PHP.
If you have no problem rebuilding the PHP binary, I managed to port this feature from PHP 7.3 to PHP 5.6.40, and there is now a pull request.
I needed it for our projects that aren't migrated yet.
I know 5.6 branch is deprecated, I am just sharing.
Pull request:
https://github.com/php/php-src/pull/6446
Our repo with the changes:
https://github.com/Inducido/php-src/tree/PHP-5.6.40
Build tested on Debian 8.11
New Feature
Session:
. Added support for the SameSite cookie directive for setcookie(),
setrawcookie() and session_set_cookie_params().
Port from PHP 7.x branch
they all have an "samesite" additionnal parameter at the very end (string)
prototypes:
bool setcookie(string name [, string value [, int expires [, string path [, string domain [, bool secure[, bool httponly[, string samesite]]]]]]])
bool setrawcookie(string name [, string value [, int expires [, string path [, string domain [, bool secure[, bool httponly[, string samesite]]]]]]])
void session_set_cookie_params(int lifetime [, string path [, string domain [, bool secure[, bool httponly[, string samesite]]]]])
(session_get_cookie_params updated too)
Changes to INI File Handling
session.cookie_samesite
. New INI option to allow to set the SameSite directive for cookies. Defaults
to "" (empty string), so no SameSite directive is set. Can be set to "Lax"
or "Strict", or "None" which sets the respective SameSite directive.
when using "None", make sure to include the quotes, as none is interpreted
like false in ini files.
This solves the issue "This Set-Cookie was blocked due to user preferences" in Chrome.
If you use nginx, you can also modify the cookie using lua. It is a bit hacky, but I found it to be working well for legacy sites:
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php5.6-fpm.sock;
# This is the relevant part:
header_filter_by_lua '
local cookies = ngx.header.set_cookie
if cookies then
if type(cookies) ~= "table" then
cookies = {cookies}
end
local gsub = string.gsub
local changed
for i, cookie in ipairs(cookies) do
local new_cookie = gsub(cookie, "^PHPSESSION=(.*)", "PHPSESSION=%1; Samesite=strict", 1)
if new_cookie ~= cookie then
cookies[i] = new_cookie
changed = true
end
end
if changed then
ngx.header.set_cookie = cookies
end
end
';
# End Lua
}
You might need to adapt the regex (gsub), but I found it works well.
Have seen the usage for session_set_cookie_params domain parameter as null like below.
session_set_cookie_params('604800', '/', null, true, true);
Consulting the documentation it suggests that for domain:
session.cookie_domain string
session.cookie_domain specifies the domain to set in the session cookie. Default is none at all.....
Thus enquiring if
null
is a right value to use here or should actually
none
I suppose you made a mistake with a translation. If the attribute-value is empty, the behavior is undefined according to cookies specification.
https://www.rfc-editor.org/rfc/rfc6265#section-5.2.3
If you want to leave this param empty you should use null or ''. You can't set 'none' for this purpose.
I only want the session cookie on www.website.tld and www.apps.website.tld, using ini_set if possible. Also i need to set all cookies i write to both subdomains only. I do not want www.imgs.website.tld to have the cookies. the php session one i'm kinda unsure of. The cookies i set my self my idea was to call SetBothCookie($name,$value,$time) a custom function.
function SetBothCookie($name,$value,$time)
{
setcookie($name, $value, $time, "", "www.website.tld", 1);
setcookie($name, $value, $time, "", "www.apps.website.tld", 1);
}
So i think i have the SetBothCookie part down, but wanted to see what others think of that code. The part i'm stuck on is having php set the session cookie on both sub domains. I'm using session_set_save_handler to override the default php session storage to store sessions in the database, so both servers can use the same session data. From my understanding is if i put Javascript that does http requests on the www.apps.website.tld to www.website.tld it won't allow them to happen, and i want that added security, so thats my reason of running only a part of the site on a subdomain.
This function should work but...
Using secure parameter in set_cookie() according to PHP manual
Indicates that the cookie should only
be transmitted over a secure HTTPS
connection from the client. When set
to TRUE, the cookie will only be set
if a secure connection exists. On the
server-side, it's on the programmer to
send this kind of cookie only on
secure connection (e.g. with respect
to $_SERVER["HTTPS"]).
So I suggest to remove 6th parameter of set_cookie() function.
Also, you can call this function before any output or it will throw a warning like
Warning: Cannot modify header
information - headers already sent by
(output started at ...) in ... on line XX
Using session_set_save_handler() is good solution to take control over session variables.
If you want cookies for entire domain just use "/" or ".website.tld" (with initial dot according to RFC 2109 standard) for domain parameter (5th in a row). Parameter path should be "" (empty string; 4th).
I came across the snippet below:
setcookie('foo', 'v1', time() + 60*60*24, '/');
setcookie('foo', 'v2');
What is the effect of setting 2
cookies with same name but different
values?
Is it common in practice?
Where is it used?
The above example will simply overwrite the first cookie with the second one. If you want to update a cookie to store a newer value, you can overwrite its value.
Two cookies may have the same name if they were set for different domains or paths. example :
<?php
setcookie("testcookie", "value1forhost", time(), "/", ".domain.com", 0, true);
setcookie("testcookie", "value2forsubdom", time(), "/", "subdom.domain.com", 0, true);
?>
The v1 vs v2 part makes it look like a trick to detect a cookie handling bug in the browser: if foo equals v1, the browser did not process the value change.
It'd be interesting to know about the code context.
Edit
Will it set 2 cookies or will it
overwrite
It depends on where you call the script from. A setcookie() call without a path sets a cookie for current path (where path is an URL path, not the internal file system path). So a call from http://example.com/ would create a single cookie and a call from http://example.com/somewhere/inside/ would crate two separate cookies, one for / and one for /somewhere/inside/.
I think this is not intended. The second cookie call will overwrite the original set cookie. After the first call there is no knowing if browser support is available, as no input from the browser is received when processing a script. A cookie is sent as a HTTP header, and sent back by the browser on consecutive requests.