现在的位置: 首页 > 综合 > 正文

PHP session的详细分析

2013年08月28日 ⁄ 综合 ⁄ 共 4653字 ⁄ 字号 评论关闭

  

2.7 如何删除session

(1) unset ($_SESSION['xxx']) 删除单个session,unset($_SESSION['xxx']) 用来unregister一个已注册的session变量。其作用和session_unregister()相同。session_unregister()在PHP5中不再使用,可将之打入冷宫。
unset($_SESSION) 此函数千万不可使用,它会将全局变量$_SESSION销毁,而且还没有可行的办法将其恢复。用户也不再可以注册$_SESSION变量。

(2) $_SESSION=array() 删除多个session

(3) session_destroy()结束当前的会话,并清空会话中的所有资源。该函数不会unset和当前session相关的全局变量(globalvariables),也不会删除客户端的session cookie.PHP默认的session是基于cookie的,如果要删除cookie的话,必须借助setcookie()函数。

下面是PHP官方关于删除session的案例:
<?php
// 初始化session.
session_start();
/*** 删除所有的session变量..也可用unset($_SESSION[xxx])逐个删除。****/
$_SESSION = array();
/***删除sessin id.由于session默认是基于cookie的,所以使用setcookie删除包含session id的cookie.***/
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time()-42000, '/');
}
// 最后彻底销毁session.
session_destroy();
?>

由此我们可以得出删除Session的步骤:
①session_start()
②$_SESSION=array()/unset($_SESSION['xxx'])
③session_destroy()

3. Session跨页传递问题:

3.1有两种方法传递一个会话 ID: cookie URL 参数

会话模块支持这两种方法。cookie 更优化,但由于不总是可用,也提供替代的方法。第二种方法直接将会话 ID 嵌入到 URL 中间去。

PHP 可以透明地转换页面之间的链接。如果使用低于PHP 4.2的版本,则需要手工在编译 PHP 时激活,在 Unix 下,用 --enable-trans-sid 配置选项。如果此配置选项和运行时选项 session.use_trans_sid 都被激活(修改php.ini),相对 URI 将被自动修改为包含会话 ID。

Note: 非相对的 URL 被假定为指向外部站点,因此没有附加 SID,因为这可能是个安全隐患将 SID 泄露给不同的服务器。

另外,也可以用常量 SID。如果客户端没有发送会话 cookie ,则 SID 的格式为 session_name=session_id,否则就为一个空字符串。因此可以无条件将其嵌入到 URL 中去。

3. 2 解决session跨页传递问题的三条途径
①客户端禁用了cookie。
②浏览器出现问题,暂时无法存取cookie
③php.ini中的session.use_trans_sid = 0或者编译时没有打开--enable-trans-sid选项

当客户端的Cookie被禁用或出现问题时,PHP会自动把session id附着在URL中,这样再通过session id就能跨页使用session变量了。但这种附着也是有一定条件的:“php.ini中的session.use_trans_sid = 1或者编译时打开打开了--enable-trans-sid选项”;

明白了以上的道理,我们就可以得出解决session跨页传递问题的三条途径:
1、设置php.ini中的session.use_trans_sid = 1或者编译时打开打开了--enable-trans-sid选项,让PHP自动跨页传递session id。

(有人说:但在测试的时候,修改php.ini哪种方式在页面中用header('location: xx.php') 和javascript window.location=xx.php 情况下没有达到想要的效果。目前发现在<a href='xx.php'>xx</a>中正常。)
2、手动通过URL传值、隐藏表单传递session id。
3、用文件、数据库等形式保存session_id,在跨页过程中手动调用。
下面举例说明:
第一种情况:
page1.php
<?php
session_start();
$_SESSION['var1']="中华人民共和国";
$url="<a href="."\"s2.php\">下一页</a>";
echo $url;
?>
page2.php
<?php
session_start();
echo "传递的session变量var1的值为:".$_SESSION['var1'];
?>
运行以上代码,在客户端cookie正常的情况下,应该可以在得到结果“中华人民共和国”。
现在你手动关闭客户端的cookie,再运行,可能得不到结果了吧。如果得不到结果,再“设置php.ini中的session.use_trans_sid = 1或者编译时打开打开了--enable-trans-sid选项”,又得到结果“中华人民共和国”

第二种途径:
s1.php
<?php
session_start();
$_SESSION['var1']="中华人民共和国";
$sn = session_id();

//PHP5定义了一个常量SID来表示session_id(),$url还可以写成$url='<a href="page2.php?' . SID . '">下一页</a>';

$url="<a href="."\"s2.php?s=".$sn."\">下一页</a>";  

echo $url;
?>

s2.php

<?php
session_id($_GET['s']);
session_start();
echo "传递的session变量var1的值为:".$_SESSION['var1'];
?>

第三种途径:
login.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Login</title>
<meta http-equiv="Content-Type" content="text/html; charset=??????">
</head>
<body>
请登录:
<form name="login" method="post" action="mylogin1.php">
用户名:<input type="text" name="name"><br>
口 令:<input type="password" name="pass"><br>
<input type="submit" value="登录">
</form>
</body>
</html>

mylogin1.php

<?php
$name=$_POST['name'];
$pass=$_POST['pass'];
if(!$name || !$pass) {
echo "用户名或密码为空,请<a href=\"login.html\">重新登录</a>";
die();
}
if (!($name=="laogong" && $pass=="123")) {
echo "用户名或密码不正确,请<a href=\"login.html\">重新登录</a>";
die();
}
//注册用户
ob_start();                             // Turn on output buffering
session_start();
$_SESSION['user']= $name;
$psid=session_id();
$fp=fopen("e:\\tmp\\phpsid.txt","w+");
fwrite($fp,$psid);
fclose($fp);
//身份验证成功,进行相关操作
echo "已登录<br>";
echo "<a href=\"mylogin2.php\">下一页</a>";
?>

mylogin2.php
<?php
$fp=fopen("e:\\tmp\\phpsid.txt","r");
$sid=fread($fp,1024);
fclose($fp);
session_id($sid);
session_start();
if(isset($_SESSION['user']) && $_SESSION['user']="laogong" ) {
   echo "已登录!";
}
else {
//成功登录进行相关操作
echo "未登录,无权访问";
echo "请<a href=\"login.html\">登录</a>后浏览";
die();
}
?>

4.关于多服务器共享同一session的解决办法

   稍大一些的网站,通常都会有好几个服务器,每个服务器运行着不同功能的模块,使用不同的二级域名,而一个整体性强的网站,用户系统是统一的,即一套用户名、密码在整个网站的各个模块中都是可以登录使用的。各个服务器共享用户数据是比较容易实现的,只需要在后端放个数据库服务器,各个服务器通过统一接口对用户数据进行访问即可。但还存在一个问题,就是用户在这个服务器登录之后,进入另一个服务器的别的模块时,仍然需要重新登录,这就是一次登录,全部通行的问题,映射到技术上,其实就是各个服务器之间如何实现共享 SESSION
数据的问题。

想要共享 SESSION 数据,那就必须实现两个目标:一个是各个服务器对同一个客户端产生的 SESSION ID 必须相同,并且可通过同一个 COOKIE 进行传递,也就是说各个服务器必须可以读取同一个名为 PHPSESSID 的 COOKIE;另一个是 SESSION 数据的存储方式/位置必须保证各个服务器都能够访问到。简单地说就是多服务器共享客户端的 SESSION ID,同时还必须共享服务器端的 SESSION 数据。

第一个目标的实现其实很简单,只需要对 COOKIE 的域(domain)进行特殊地设置即可,默认情况下,COOKIE 的域是当前服务器的域名/IP 地址,而域不同的话,各个服务器所设置的 COOKIE 是不能相互访问的,如
www.aaa.com 的服务器是不能读写
www.bbb.com
服务器设置的 COOKIE 的。这里我们所说的同一网站的服务器有其特殊性,那就是他们同属于同一个一级域,如:aaa.infor96.com 和
www.infor96.com 都属于域 .infor96.com,那么我们就可以设置 COOKIE 的域为 .infor96.com,这样 aaa.infor96.com、www.infor96.com 等等都可以访问此 COOKIE。PHP 代码中的设置方法如下:

CODE:

ini_set('session.cookie_domain', '.infor96.com');

第二个目标的实现可以使用文件共享方式,如 NFS 方式,但设置、操作上有些复杂。我们可以参考先前所说的统一用户系统的方式,即使用数据库来保存 SESSION 数据,这样各个服务器就可以方便地访问同一个数据源,获取相同的 SESSION 数据了。

抱歉!评论已关闭.