Session 函数
在线手册:中文 英文
PHP手册


Session 函数
在线手册:中文 英文
PHP手册
PHP手册 - N: Set the session cookie parameters

用户评论:

Danack dot Ackroyd at gmail dot com (30-Jun-2011 09:20)

Setting the domain for cookies in session_set_cookie_params() only affects the domain used for the session cookie which is set by PHP.

All other cookies set by calling the function setcookie() either:
i) Use the domain set explicitly in the call to setcookie()
or
ii) Don't set the domain at all on the cookie and so the browser assumes it's for the current domain.

So to make all your cookies be available across all sub-domains of your site you need to do this:

<?php
$currentCookieParams
= session_get_cookie_params();

$rootDomain = '.example.com';

session_set_cookie_params(
   
$currentCookieParams["lifetime"],
   
$currentCookieParams["path"],
   
$rootDomain,
   
$currentCookieParams["secure"],
   
$currentCookieParams["httponly"]
);

session_name('mysessionname');
session_start();

setcookie($cookieName, $cookieValue, time() + 3600, '/', $rootDomain);
?>

php at rijkvanwel dot nl (29-Oct-2010 10:32)

No matter how your server's gc is configured, a user will still experience an expired session when the cookie containing his session id is dropped.

The problem (that some people before me have already noticed) with this is, that the cookie's timestamp is not updated on every new request. So while the visitor's navigating through your site or application, his session file's timestamp is updated and your gc_lifetime is configured properly so the file's not deleted by the server, but meanwhile the clock is ticking away on his locally stored session cookie. When it reaches the time limit: boom, session gone. (Actually, the session is still there on the server, the browser just stops sending the id with the requests, so the server can't identify the visitor and starts a new session.)

One solution for this is to regenerate the cookie with each request (either by manually overwriting the cookie with setcookie(), or by regenerating the session id with session_regenerate_id()). However, this is needless overhead.

If it works for your application, a better and much simpler solution is to just set the session cookie's lifetime to 0 (which will make it live until the browser is closed):

<?php
session_set_cookie_params
(0);
session_start();
?>

You will only have to do this the first time your session is started (as this is the only time the cookie is sent to the client).

final dot wharf at gmail dot com (28-Oct-2010 03:42)

As PHP's Session Control does not handle session lifetimes correctly when using session_set_cookie_params(), we need to do something in order to change the session expiry time every time the user visits our site. So, here's the problem.

<?php
  $lifetime
=600;
 
session_set_cookie_params($lifetime);
 
session_start();
?>

This code doesn't change the lifetime of the session when the user gets back at our site or refreshes the page. The session WILL expire after $lifetime seconds, no matter how many times the user requests the page. So we just overwrite the session cookie as follows:

<?php
  $lifetime
=600;
 
session_start();
 
setcookie(session_name(),session_id(),time()+$lifetime);
?>

And now we have the same session cookie with the lifetime set to the proper value.

digitalmagnets at gmail dot com (31-Mar-2010 09:36)

It appears that if you are setting a session cookie on https://subdomain123.example.com for .example.com that the default of the secure cookie is not false but true.

So your cookie won't work on http://subdomainxyz.example.com unless you set the secure option to false.

jan at dewal dot net (19-Mar-2010 10:42)

The information above about this function that it can only be used BEFORE session_start depends on how you use it. Because its also useful AFTER a session has started as follows:

Example you wand to change an already set value of the session cookie expire time:

<?php

 
// Here we start as usual
session_set_cookie_params('3600'); // 1 hour
session_start();

// More code...

// Now we found in some database that the user whishes
// the cookie to expire after for example 10 minutes
// we can change it instantly !

session_set_cookie_params('600'); // 10 minutes.
session_regenerate_id(true);

// This will delete old cookie and adopt new expire settings and the
// old cookie variables in a new cookie

?>

Please note i only explained the browser (client) side changes of session cookie's expire time.

quintellarosa at yahoo dot com dot br (25-Feb-2010 02:27)

Thanks to dan at vespernet dot co dot uk and MaxTheDragon at NOSPAMhome dot nl, I've started solving some issues here.

I've found that using:

<?php

  session_name
($name);
 
setcookie($name, $_COOKIE[$name], time() + $lifetime, $path, $domain, $secure, $httponly);
 
session_start();

?>

works fine, while:

<?php

  session_name
($name);
 
session_set_cookie_params($lifetime, $path, $domain, $secure, $httponly);
 
session_start();

?>

doesn't seem to work properly, like not updating the lifetime properly.

For anyone interested. Any comments would be appreciated.

Miki (04-Dec-2009 06:13)

REMEMBER, that if you have a multi-subdomain site, you must put the following to enable a session id on the whole website:

<?php
session_set_cookie_params
(0, '/', '.example.com');
session_start();
?>

Otherwise, you'll have 2 diffrent sessions on e.g. news.example.com and download.example.com

seth36 at gmail dot com (28-Jul-2009 09:13)

I've found session_set_cookie_params to be ineffective at changing the session lifetime, to change the session lifetime I do the following:

<?php

$Lifetime
= 3600;
$Seperator = (strstr(strtoupper(substr(PHP_OS, 0, 3)), "WIN")) ? "\\" : "/";
$DirectoryPath = dirname(__FILE__) . "{$Seperator}SessionData";
is_dir($DirectoryPath) or mkdir($DirectoryPath, 0777);

if (
ini_get("session.use_trans_sid") == true) {
   
ini_set("url_rewriter.tags", "");
   
ini_set("session.use_trans_sid", false);

}

ini_set("session.gc_maxlifetime", $Lifetime);
ini_set("session.gc_divisor", "1");
ini_set("session.gc_probability", "1");
ini_set("session.cookie_lifetime", "0");
ini_set("session.save_path", $DirectoryPath);
session_start();

?>

I switched to this after having many failed attempts at having a session remain active for longer than the default 24 minutes, the problem it seems is what many suggest that appears to be wrong - Setting the cookie lifetime to be the same as session.gc_maxlifetime, although the expiry of the cookie is set, it isn't updated when the user remains active in the session, so even if the session is actively being used, once the cookie life runs out, the sessions gets invalidated, using the above seems to work for me.

Ashus (18-Nov-2008 03:38)

Cross-domain Cookies do work in all browsers (path '/' server '.example.com'), except the case you try it in IE6/7 and the server name is retreived from :etc/hosts: file, in that case the cookie won't be even saved.

Anonymous (14-Aug-2008 07:42)

In Response to RC
>23-Apr-2008 04:45
>For anyone looking for which browsers support the HTTPOnly >flag, per my research:
>
>IE 6 SP 1 and higher.
>Firefox 3 and higher.
>Opera 9.50 and higher.

Firefox 2.0 also supports them, but only since version 2.0.0.5.

http://bugzilla.mozilla.org/show_bug.cgi?id=178993

brandan, bildungsroman.org (28-May-2008 04:55)

i found it somewhat difficult to work with sessions due to the documentation not really denoting the necessity for the session name to be set via session_name() in order for session_set_cookie_params() to be of any use.  i found no reference to session_name() in this article, and my session functions would have been a disastrous mess were it not for a friend familiar with session.

so, in essence, for anybody wondering about where to start: declare a session name before using session_set_cookie_params(), otherwise you might agitate php to the point of committing some atrocity against your webserver.

RC (23-Apr-2008 03:45)

For anyone looking for which browsers support the HTTPOnly flag, per my research:

IE 6 SP 1 and higher.
Firefox 3 and higher.
Opera 9.50 and higher.

As of Safari 3.1.1 (April 2008), Safari did not yet support this flag.

This cookie flag was developed by Microsoft and is slowly making its way into other browsers: http://msdn2.microsoft.com/en-us/library/ms533046.aspx

eddie at roosenmaallen dot com (15-Mar-2008 02:49)

Further to "info at xyzsite dot ru" and William Leslie, Safari on OS X also doesn't honour cookies with an underscore in the subdomain.

The workaround I've found is to specify the parent domain as the cookie domain -- instead of "bad_name.example.com", set the path to ".example.com"; it's suboptimal, but gets the job done.

William Leslie (08-Feb-2008 05:32)

"Info at xyzsite dot ru" writes that Internet Explorer does not correctly handle cookies whose domain contains an underscore character.

However, There's a good reason for this apparently faulty behavior: the underscore character is forbidden in DNS names.  RFC 3696 says:

"The labels ... that make up a domain name must consist of only the ASCII alphabetic and numeric characters, plus the hyphen.  No other symbols or punctuation characters are permitted, nor is blank space."

If the underscore works in Mozilla or other browsers, it's only because they are being lenient in the validation of domain names.

info at xyzsite dot ru (20-Dec-2007 04:27)

Just one more bad situation - cookies in Internet Explorer do not work with '_' in domain name. FF and Opera are O.K. So if your hostname is like test_host.example.com, IE cookies will not function correctly/

dan at vespernet dot co dot uk (02-Nov-2007 07:38)

The below note is an excellent example of how to 'reset' the session expiration time upon a page refresh.

However, take care to compensate for when the session expires and doesn't renew itself (a bug I believe). If the below example is run every time a script is executed, it will give an 'Undefined index <session name> error' after the session fails to renew. Precede it with and if isset() condition.

<?php
private function startSession($time = 3600, $ses = 'MYSES') {
   
session_set_cookie_params($time);
   
session_name($ses);
   
session_start();

   
// Reset the expiration time upon page load
   
if (isset($_COOKIE[$ses]))
     
setcookie($ses, $_COOKIE[$ses], time() + $time, "/");
}
?>

The above example states that a session will last an hour without a page refresh until it is scrapped. Upon a page refresh, the expiration time is reset back to one hour again. If you wish to give users the option of 'staying logged in forever', just feed startSession a value of '99999999', which should last about 3 years.

MaxTheDragon at NOSPAMhome dot nl (10-Sep-2007 09:46)

This article states that one must define the lifetime of the cookie using session_set_cookie_params(), before calling session_start(). This is correct.

However, suppose you would need to change the session cookie lifetime, during the session. You would have to delete the session in order to pass the correct lifetime. If however, the session contains important data, you might not want to delete the session.

This seems to be a problem, since the session already exists.

The following code:

<?php
setcookie
(session_name(), $_COOKIE[session_name()], time()+10000, "/");
?>

allows you to change the cookie lifetime, during the session, and without the need to delete the session. Basically it grabs the existing cookie, and just updates the lifetime, leaving the data intact.

<?php
setcookie
(session_name(), $_COOKIE[session_name()], 0, "/");
?>

Similarly, the above code allows you to turn the existing session, into one that is destroyed, when the browser screen closes.

Please note that this is not a replacement of session_set_cookie_params! You must still call that function before the session start to set a lifetime for the cookie. If somewhere after the session_start(), you need to change the lifetime, use the code supplied above, and also make sure that the new lifetime gets included in the next calls of
session_set_cookie_params(). This ensures that the cookie will work properly with the new lifetime, even after page browsing/refreshes.

I have tested this, and it seems to work properly.

jordi at jcanals dot net (15-Nov-2004 01:39)

Something that has taken me some time to debug: session_set_cookie_params() does not work when the domain param is just a one level domain, like it was a TLD.

I have a site in an intranet and our internal domain is .local, so trying to set the cookie session to the .local domain does not work:

session_set_cookie_params(0, '/', '.local'); // Does not work

In all test I've done, setting the domain only works for SLDs and above:

session_set_cookie_params(0 , '/', '.sld.local'); Does work

This is nothing to do with PHP but the http protocol, witch does not permit setting cookies for TLDs for obvious security reasons.

shrockc at inhsNO dot SPAMorg (19-Jun-2002 05:19)

when setting the path that the cookie is valid for, always remember to have that trailing '/'.

CORRECT:
session_set_cookie_params (0, '/yourpath/');

INCORRECT:
session_set_cookie_params (0, '/yourpath');

no comment on how long it took me to realize that this was the cause of my authentication/session problems...

gavin_spam at skypaint dot com (26-Feb-2002 10:58)

The first argument to session_set_cookie_params is the number of seconds in the future (based on the server's current time) that the session will expire.  So if you want your sessions to last 100 days:

$expireTime = 60*60*24*100; // 100 days
session_set_cookie_params($expireTime);

I was using time()+$expireTime, which is WRONG (a lot of the session_set_cookie_params() examples I found get this wrong, but probably don't care because they are just doing "infinite" sessions).

php at mike2k dot com (09-May-2001 10:16)

[Editor's Note:

Rasmus' Solution from the PHP-General list:

Just use a session cookie (by not providing an expiry time) and add the
server's expiry timestamp to the value of the cookie.  Then when you get
that cookie sent to you, check it against your server's time and make the
decision on whether to accept the cookie or not based on that.

That way you are immune from people not having their system clocks set
right.

-Rasmus

--zak@php.net]

A couple things I noticed when using this. I think it only works if you set the session_set_cookie_params() function BEFORE the session_start() function.

Also, when you set the "lifetime" on the cookie, it takes the seconds offset from the SERVER. it sends the cookie encoded to timeout at the SERVER time. So if your server is +2 minutes ahead of the client, and you set the cookie to timeout after 30 seconds, the client actually has 2 minutes and 30 seconds before the cookie times out. I don't know if there's any way that this can be patched in future versions, and the only alternative I think is setting cookies in javascript, which is hardly the point when using all these specific session functions.