PHP Conference Japan 2024
添加注释

用户贡献的注释 20 条注释

145
final dot wharf at gmail dot com
14 年前
由于 PHP 的会话控制在使用 session_set_cookie_params() 时无法正确处理会话生存期,因此我们需要执行某些操作才能在用户每次访问我们的网站时更改会话过期时间。这就是问题所在。

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

这段代码不会在用户返回我们的网站或刷新页面时更改会话的生存期。无论用户请求页面多少次,会话都将在 $lifetime 秒后过期。因此,我们只需如下覆盖会话 Cookie

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

现在我们有了具有设置为正确值的生存期的相同会话 Cookie。
51
frank at frankforte dot ca
4 年前
以下内容似乎适用于为 PHP < 7.3 设置会话 Cookie 上的 SameSite 属性。

<?php

$secure
= true; // 仅当通过 HTTPS 接收 cookie 时才使用
$httponly = true; // 防止 JavaScript 访问会话 cookie
$samesite = 'lax';

if(
PHP_VERSION_ID < 70300) {
session_set_cookie_params($maxlifetime, '/; samesite='.$samesite, $_SERVER['HTTP_HOST'], $secure, $httponly);
} else {
session_set_cookie_params([
'lifetime' => $maxlifetime,
'path' => '/',
'domain' => $_SERVER['HTTP_HOST'],
'secure' => $secure,
'httponly' => $httponly,
'samesite' => $samesite
]);
}
?>
7
theking2(at)king.ma
1年前
根据PHP 7版本,`session_start`可以包含一个选项数组,这个函数已过时。所有cookie设置(以及更多)都可以作为参数包含在`session_start()`的选项数组中。

<?php
session_start
( [
'cookie_path' => '/',
'cookie_lifetime' => 300,
'cookie_secure' => true,
'cookie_httponly' => true,
'cookie_samesite' => 'lax',
] );
14
passerbyxp at gmail dot com
12年前
需要注意的是,浏览器对`$path`参数的大小写敏感。

例如,如果您这样做
<?php
session_set_cookie_params
(0,"/webapp/");
session_start();
?>

并且您以这种方式访问您的网站
example.com/WebApp/

每次请求都会获得一个新的会话。

我不确定这是否是标准做法,但我发现这发生在IE 6、Firefox 12(实际上是Palemoon)、Chrome 19(便携式版本)以及IIS和Apache上。
19
Danack dot Ackroyd at gmail dot com
13年前
在`session_set_cookie_params()`中设置cookie的域名只影响PHP设置的会话cookie使用的域名。

通过调用`setcookie()`函数设置的所有其他cookie:
i) 使用在`setcookie()`调用中明确设置的域名
或者
ii) 完全不设置cookie的域名,因此浏览器假定它是当前域名的cookie。

因此,要使所有cookie都可在您网站的所有子域中使用,您需要这样做:

<?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);
?>
14
shrockc at inhsNO dot SPAMorg
22年前
设置cookie有效路径时,请务必记住末尾的'/'。

正确
session_set_cookie_params (0, '/yourpath/');

错误
session_set_cookie_params (0, '/yourpath');

我花了很长时间才意识到这就是我的身份验证/会话问题的原因……
11
werner dot avenant at gmail dot com
12年前
请注意Ubuntu和Debian等系统上的垃圾回收“功能”。

apt-get在`/etc/cron.d/php5`安装一个cron脚本,该脚本检查`session.gc_maxlifetime`变量,然后每9分钟和39分钟删除所有旧会话。

问题是:如果您为特定的虚拟主机设置了`maxlifetime`,则这些设置将被忽略。假设您希望服务器仅存储30分钟的会话,但对于一个特殊的网站,您希望所有会话都持续24小时。如果您在`.htaccess`、apache配置文件中设置`session.gc_maxlifetime`或在代码中使用`ini_set`,它将不起作用,会话仍然会在30分钟后被销毁。这是因为`/usr/lib/php5/maxlifetime`(在该cron文件中找到)将始终返回`php.ini`中的值,而不是您在`.htaccess`中设置的值。

一种解决方法是将`maxlifetime`设置为您的网站所需的最大值,然后为不需要它的网站在`.htaccess`中配置更短的`maxlifetime`。

另一种解决方案是为`/etc/cron.d`中的`php5`文件提供合理的数值,例如,只让它在凌晨3点运行,但您必须记住每次更新php时都要阻止替换此文件。
13
Miki
15年前
记住,如果您有多个子域的站点,则必须设置以下内容才能在整个网站上启用会话ID:

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

否则,您将在例如news.example.com和download.example.com上拥有两个不同的会话。
5
jordi at jcanals dot net
20年前
我花了一些时间来调试的一件事是:当域名参数只是一个一级域名(就像顶级域名一样)时,`session_set_cookie_params()`不起作用。

我在内网上有一个站点,我们的内部域名是`.local`,因此尝试将cookie会话设置为`.local`域名不起作用。

session_set_cookie_params(0, '/', '.local'); // 不起作用

在我所做的所有测试中,设置域名只对二级域名及以上有效。

session_set_cookie_params(0 , '/', '.sld.local'); // 起作用

这与PHP无关,而是与HTTP协议有关,出于安全原因,HTTP协议不允许为顶级域名设置cookie。
6
dan at vespernet dot co dot uk
17年前
下面的说明是如何在页面刷新时“重置”会话过期时间的极好示例。

但是,请注意,当会话过期且无法自行更新时(我相信这是一个错误)需要进行补偿。如果下面的示例每次执行脚本时都运行,则在会话无法更新后,它会返回“未定义索引<会话名称>错误”。在它前面加上一个`isset()`条件。

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

// 页面加载时重置过期时间
if (isset($_COOKIE[$ses]))
setcookie($ses, $_COOKIE[$ses], time() + $time, "/");
}
?>

上面的示例表明,在会话被删除之前,会话将持续一个小时而无需页面刷新。页面刷新后,过期时间将再次重置为一小时。如果您希望允许用户“永远保持登录状态”,只需为`startSession`提供'99999999'的值,这应该持续大约3年。
4
匿名
16年前
回复RC
>2008年4月23日 04:45
>对于任何寻找支持HTTPOnly标志的浏览器的人,根据我的研究
>
>IE 6 SP 1及更高版本。
>Firefox 3及更高版本。
>Opera 9.50及更高版本。

Firefox 2.0也支持它们,但仅从2.0.0.5版本开始。

http://bugzilla.mozilla.org/show_bug.cgi?id=178993
1
theking2(at)king.ma
9个月前
为了完全控制会话cookie,我使用这段代码:

<?php
session_set_cookie_params
( [
'lifetime' => 0,
'path' => '/',
'domain' => $_SERVER['HTTP_HOST'],
'samesite' => 'Strict',
] );
session_start( [
'name' => 'SESSION',
'sid_length' => 96,
'sid_bits_per_character' => 6,
'use_strict_mode' => true,
'referer_check' => $_SERVER['HTTP_HOST'],
] );
?>

这会将参数设置为推荐的参数,并生成质量合理的cookie ID。
0
eion at robbmob dot com
3年前
不幸的是,`session_set_cookie_params()`不能在活动会话期间调用,它只会返回E_WARNING和false,这意味着调用`session_regenerate_id()`(例如,在登录期间防止会话固定攻击)最终可能使用旧的cookie设置(例如,不是“SameSite=Strict”)。

为确保将来创建的所有会话都使用正确的cookie设置,最好使用ini_set()设置cookie参数——session_set_cookie_params()在其底层也是这么做的。
1
jan at dewal dot net
14 年前
关于此函数的信息(只能在session_start之前使用)取决于你的使用方法。因为它在会话启动后也可用,如下所示:

例如,你想更改已设置的会话cookie过期时间值。

<?php

// 我们像往常一样开始
session_set_cookie_params('3600'); // 1小时
session_start();

// 更多代码...

// 现在我们在某个数据库中发现用户希望
// cookie 例如在 10 分钟后过期
// 我们可以立即更改它!

session_set_cookie_params('600'); // 10分钟。
session_regenerate_id(true);

// 这将删除旧的cookie并采用新的过期设置和
// 新cookie中的旧cookie变量

?>

请注意,我只解释了会话cookie过期时间的浏览器(客户端)端更改。
0
gavin_spam at skypaint dot com
22年前
session_set_cookie_params的第一个参数是会话过期时间的秒数(基于服务器的当前时间)。所以如果你想让你的会话持续100天

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

我之前使用的是time()+$expireTime,这是错误的(我找到的许多session_set_cookie_params()示例都错了,但可能并不在意,因为他们只是做“无限”会话)。
0
php at mike2k dot com
23年前
[编辑注]

来自PHP-General列表的Rasmus的解决方案

只需使用会话cookie(不提供过期时间)并将
服务器的过期时间戳添加到cookie的值中。然后当你得到
发送给你的cookie时,将其与服务器的时间进行比较,并根据该时间
决定是否接受cookie。

这样你就不会受到系统时钟设置不正确的人的影响。
正确。

-Rasmus

[email protected]]

使用它时我注意到了一些事情。我认为它只有在你设置session_set_cookie_params()函数在session_start()函数之前才有效。

此外,当你设置cookie的“生命周期”时,它会采用服务器的秒偏移量。它发送编码的cookie以便在服务器时间超时。所以如果你的服务器比客户端快2分钟,而你将cookie设置为30秒后超时,那么客户端实际上有2分30秒的时间才能使cookie超时。我不知道这是否可以在将来的版本中进行修补,我认为唯一的替代方法是在javascript中设置cookie,当使用所有这些特定的会话函数时,这几乎没有意义。
-1
William Leslie
16年前
"Info at xyzsite dot ru" 写道,Internet Explorer无法正确处理域名包含下划线的cookie。

然而,这种明显错误的行为有一个很好的理由:下划线在DNS名称中是被禁止的。RFC 3696指出

"构成域名...的标签必须仅由ASCII字母数字字符和连字符组成。不允许使用其他符号或标点符号,也不允许使用空格。"

如果下划线在Mozilla或其他浏览器中有效,那只是因为它们在域名验证方面比较宽松。
-2
Ashus
16年前
跨域Cookie在所有浏览器中都能工作(路径'/' 服务器'.example.com'),除了你在IE6/7中尝试它并且服务器名称是从:/etc/hosts:文件中检索到的情况,在这种情况下,cookie甚至不会被保存。
-3
brandan, bildungsroman.org
16年前
我发现由于文档没有真正说明为了使session_set_cookie_params()发挥作用而必须通过session_name()设置会话名称的必要性,因此使用会话有些困难。我在本文中没有找到关于session_name()的任何参考,如果我的朋友不熟悉会话,我的会话函数就会是一团糟。

因此,从本质上讲,对于任何想知道从哪里开始的人:在使用session_set_cookie_params()之前声明一个会话名称,否则你可能会激怒php,以至于它对你的web服务器进行一些暴行。
-5
eddie at roosenmaallen dot com
16年前
进一步补充"info at xyzsite dot ru"和William Leslie的观点,OS X上的Safari也不支持子域名中带有下划线的cookie。

我找到的解决方法是将父域名指定为cookie域名——而不是"bad_name.example.com",将路径设置为".example.com";这并非最佳方案,但可以完成任务。
To Top