一、关于SESSION
SESSION:
用于管理不同的客户端会话。简单来讲,当用户向站点请求不同页面时,都应该生成一个会话ID ,用于标识不同用户。所以同一个用户在一个网站的不同页面间跳转时,应确保该会话ID 是相同的。
因此,在用户请求浏览不同页面时,应该同时将其唯一标识该用户的会话ID 传过去,将该ID 设置为当前会话ID。对应有两种方式传送session ID。
注意:
1、会话必须启动才能使用$_SESSION。(可明确通过session_start()或隐式通过 session_register(),或设置php.ini 中session.auto_start为1)
2、默认情况下(浏览器启用了cookie功能),PHP 会通过cookie传递session ID,并自动设置为当前会话ID。如:
火狐默认启用了cookie功能,则下面两个页面及其跳转结果:
页面一:testsession.php:
<?php
session_start();//开始一个会话
echo session_id()."<br/>";//打印显示当前会话的ID
if (isset($_SESSION['times'])) {
$_SESSION['times']+=1;
echo "You have visited the website ".$_SESSION['times']." times";
}
else{
echo "Welcome!";
$_SESSION['times']=1; //要保存的session数据
}
//同时设置一个cookie,用于测试cookie传递与否
if (isset($_COOKIE['user'])) {
echo $_COOKIE['user']."访问次数为:".$_SESSION['times'];
}
else{
setcookie('user','wjb',time()+100);
echo "欢迎首次访问!";
}
?>
<!DOCTYPE html>
<html>
<head>
<title>页面一</title>
<meta charset="utf-8">
</head>
<body>
<a href="testsession2.php">跳转到页面二</a>
</body>
</html>
页面二:testsession2.php:
<?php
echo session_id()."<br/>";
session_start();//开始一个会话
if (isset($_SESSION['times'])) {
echo "另一个页面取session数据times为".$_SESSION['times'];
}
else{
echo "另一个页面取回session失败";
}
?>
<!DOCTYPE html>
<html>
<head>
<title>页面二</title>
<meta charset="utf-8">
</head>
<body>
<?php
echo $_COOKIE['user']."<br/>";
?>
</body>
</html>
结果:页面一:
页面二:
可见,虽然没有人为将第一个页面的会话ID 设置为第二个页面会话(新会话)的ID ,但两个会话其实是同一个,因为,PHP 默认通过浏览器的cookie传送了会话ID并设置为新页面的会话。(默认设置的cookie名为'PHPSESSID',可通过php.ini配置)
关闭浏览器的cookie功能后,会话ID将不能通过cookie自动传送:
页面一:cookie已不能使用,即超全局变量$_COOKIE 无法设置。且每次刷新页面一得到的会话ID 都是新的。
页面二:cookie与session都没传送。
二、两种方式传送会话ID
1、URL 方式:
实际是将会话ID 放入了$_GET中
无需开发人员干预,PHP 能自动处理URL 传递会话ID 的场景。如果使用php 4.2.0之前的版本,需要使用 --enable-trans-sid参数来构建php(貌似编译时勾选该参数),然后指定session.use_trans_sid为1(默认为0),PHP将自动在相关URL 中包含会话ID。(文档的翻译,但自己并没有看到url中包含了会话ID,有空再探究。)
说明:在URL 中传送的会话ID 可能被他人利用,因而是不太安全的,但可用于用户关闭浏览器cookie功能的情况。
同样是上面两个页面,关闭浏览器cookie功能后,使用URL 传递会话ID :
页面一:使用SID 常量在URL 中传递session ID。
局部修改为:
<body>
<a href="testsession2.php?<?php echo htmlspecialchars(SID)?>">跳转到页面二</a>
</body>
局部修改为:
<?php
echo session_id()."<br/>";
echo $_GET['PHPSESSID'];//从$_GET取回session ID
session_id($_GET['PHPSESSID']);//设置为当前会话ID,会话的设置必须在session_start()前
session_start();
if (isset($_SESSION['times'])) {
echo "另一个页面取session数据times为".$_SESSION['times'];
}
else{
echo "另一个页面取回session失败";
}
?>
结果:
页面一:cookie被禁用
页面二:url中显示了session ID。设置为当前会话后,所有$_SESSION中保存的数据将能使用。因为cookie被禁用,所以提示了警告。
Note:
非相对 URL 将被视为指向外部站点的链接, 从安全角度考虑,外站的链接 URL 中将 不包含 SID
常量,以避免将SID
泄露到外部服务器的风险。
2、cookie方式
此方式不能禁用浏览器的cookie功能。
页面一:
局部修改:
session_start();
echo session_id()."<br/>";
setcookie(session_name(),session_id(),time()+60);//session_name()默认返回值为'PHPSESSID'
页面二:
局部修改:
echo $_COOKIE['PHPSESSID']."nihao";//'PHPSESSID'是默认的会话ID,可在php.ini中配置
session_id($_COOKIE['PHPSESSID']);
session_start();
页面二能通过cookie接收会话ID ,从而访问会话对应的用户数据($_SESSION与$_COOKIE中数据)。
注:
尽管页面一中设置该存储session ID的cookie 有效生存时间为60秒,但在页面二中60秒后刷新发现session_id()仍打印相同的会话ID ,可见开启cookie功能时,会话ID 应该是PHP 在脚本结束时自动存储在cookie中的。但人为设置的其它cookie数据,有效期由默认或创建时指定的值决定。
三、两种方式都使用
为了防止用户关闭cookie而不能通过cookie传送会话ID ,将两种方式都用上(没考虑安全因素)。此时页面二局部修改为:
页面二:testsession2.php:
<?php
//优先检查是否通过默认的cookie传送会话ID;cookie不可用时再检查是否通过URL 传送。
if(isset($_COOKIE['PHPSESSID'])){
session_id($_COOKIE['PHPSESSID']);
echo "通过cookie设置会话成功,id为:\n";
}
else if (isset($_GET['PHPSESSID'])) {
session_id($_GET['PHPSESSID']);
echo "通过get设置会话成功,id为:\n";
}
else
echo "设置会话失败,新的会话id为:";
echo session_id();
session_start();
if (isset($_SESSION['times'])) {
echo "另一个页面取session数据times为".$_SESSION['times'];
}
else{
echo "另一个页面取回session失败";
}
?>