天天看点

php session 不同步,PHP Session失效不传递的解决办法

在PHP中使用过SESSION的过程中,可能会碰到这么一个问题,SESSION变量不能跨页传递。这令我苦恼了好些日子,最终通过查资料思考并解决了这个问题。我认为,出现这个问题的原因有以下几点:

1、客户端禁用了cookie

2、浏览器出现问题,暂时无法存取cookie

3、php.ini中的session.use_trans_sid = 0或者编译时没有打开--enable-trans-sid选项

针对这种情况,我们可以提供两种解决思路:

1、网页做cookie是否禁用的检测,如果禁用了提示用户开启cookie再继续使用。

2、不做检测和提示,换跑道直接规避出现这种情况的可能性。即,不使用cookie来记录session_id

一、PHP中的SESSION机制说明:

在默认情况下,当访客访问网站时,php程序通过预先写好的session_start();命令在服务器端为该访客创建一个session文件,用于存储该访客的变量。

并将创建好的session文件的id发送给客户端,客户端浏览器收到该session_id时,将该session_id存储在浏览器本地cookie中。

当访客离开该网页进入其他网页时,浏览器从本地cookie中取出session_id再发送给服务端,服务端php执行到session_strart()时将不再创建新的session给该访客,而是根据该session_id获得该访客的session变量继续使用,在各个跨网页间进行变量传递,已达到跨网页传递数据和用户信息不丢失的目的。

但是,当访客的客户端浏览器如果禁用了cookie,客户端将无法保存session值,当用户离开该网页进入其他网页时,服务端无法获得session_id和继续使用该session文件,就会把访客当做新用户,再次创建一个session文件给其使用。这样以来session就无法做到跨网页传递数据的目的了。

表现出来的现象就是session失效无法跨网页传递数据。

session id可以使用客户端的Cookie或者Http1.1协议的Query_String(就是访问的URL的“?”后面的部分)来传送给服务器,并非只能使用cookie。

二、对该问题的解决方法:

1、做cookie是否禁用的检测,如果禁用了提示用户开启后再使用。

这里使用js来检测客户端浏览器cookie是否禁用。并提示

这里为了避免js也被禁用,也做了js是否禁用的检测和提示。

.close{display:none;color:red;font-size:16px;font-weight:bold;text-align:center;}

.show{color:red;font-size:16px;font-weight:bold;text-align:center;}

你禁用了javascript,请开始!否则无法使用后台! 你禁用了cookie,请开始!否则无法使用后台!

//检测是否禁用了js

var NoJs= document.getElementById("NoJs");

NoJs.className="close";

//检测是否禁用了cookie

function CookieEnable(){

var result=false;

if(navigator.cookiesEnabled)  return true;

document.cookie = "testcookie=yes;";

var cookieSet = document.cookie;

if (cookieSet.indexOf("testcookie=yes") > -1)  result=true;

document.cookie = "";

return result;

}

if(!CookieEnable()){

//alert("对不起,您的浏览器的Cookie功能被禁用,请开启");

var NoCookie= document.getElementById("NoCookie");

NoCookie.className="show";

}

2、不使用cookie存储session_id的方法:

(1)、开启透明SID

需要修改的php.ini是:

session.use_trans_sid = 1         //由0改为1

session.use_only_cookies = 0  //是否只使用cookie来保存session值  该参数为1时,上述机制失效。

session.use_cookies = 0          //设置客户端是否使用cookie来保存session值  该参数的值不影响上述机制的进行。这个可改可不改

当在php开启了透明SID后(也就是自动模式),系统会将url后面自动添加PHPSESSID参数。也就是URL的格式为:

每次自动将sessionid以get参数形式添加到url上,在每个页面直接获得get参数获得sessionid并使用即可<?php

if($_GET["PHPSESSID"]){

session_id($_GET["PHPSESSID"]);//这步必须在session_start()之前获取并确定sessionid

}

session_start();

echo session_id().'

';

(2)、如果没有修改php.ini配置文件权限,可使用手动GET传sessionid、隐藏表单传递sessionid、服务端将sessionid保存在文件中读写、将sessionid保存在数据库中。这四种方案都可以解决。

A、手动GET传值

s1.php<?php

session_start();

$_SESSION[’var1’]="中华人民共和国";

$sn = session_id();

$url="下一页";

echo $url;

?>

s2.php<?php

session_id($_GET['PHPSESSID']); //设置session_id必须要在session_start()前

session_start();

echo "传递的session变量var1的值为:".$_SESSION[’var1’];

?>

B、隐藏表单传递session_id

在form表单中,增加<?php

$sn = session_id();

?>

">

C、服务端将session保存在文件中。

login.htmlHTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

Login

请登录:

用户名:

口 令:

mylogin1.php<?php

$name=$_POST[’name’];

$pass=$_POST[’pass’];

if(!$name || !$pass) {

echo "用户名或密码为空,请重新登录";

die();

}

if (!($name=="youngong" && $pass=="123") {

echo "用户名或密码不正确,请重新登录";

die();

}

ob_start();

session_start();

$_SESSION[’user’]= $name;

$psid=session_id();

$fp=fopen("e:/tmp/phpsid.txt","w+";

fwrite($fp,$psid);

fclose($fp);

//身份验证成功,进行相关操作

echo "已登录

";

echo "下一页";

?>

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 "请登录后浏览";

die();

}

?>

注:这里可以将每个txt文件名用会员的id命名,方便读写又区分不同用户。

D、将sessionid保存在数据库中。

简单说就是当用户登录成功时,控制器获得了该用户的会员信息和sessionid,将sessionid保存到数据库表中。

当用户进入其他页面时,通过查询数据表中该会员id关联的sessionid来获得session值。如果session失效,则无法获得session值则需要重新登录。

这里就不举例了。

三、种特殊情况:就是服务器配置方面有问题,session文件的保存路径是没有读写权限的,导致session文件无法创建。

解决方法:

1、先建立一个phpinfo文件,查看下你的服务器session存放路径。

phpinfo.php<?php

phpinfo();

?>

运行该文件后查看 session.save_path 的值就是存放路径。

2、测试该存放session文件的路径是否有读写权限:

写一个文件:test.php来测试一下:

echo var_dump(is_writeable(ini_get(“session.save_path”)));

?>

如果返回bool(false),证明文件夹写权限被限制了,你可以给加上写入权限或者在PHP程序中指定一个文件夹存放session。

PHP中指定session存放路径://设置当前目录下session子文件夹为session保存路径。

$sessSavePath = dirname(__FILE__).’/session/’;

//如果新路径可读可写(可通过FTP上变更文件夹属性为777实现),则让该路径生效。

if(is_writeable(sessSavePath) && is_readable(sessSavePath) && is_readable(sessSavePath))

{

session_save_path($sessSavePath);

}else{

echo $sessSavePath." 指定session路径不可读写,请修改权限为777";

}

四、种特殊情况:Bom头原因导致Cookie无法送出。

登录成功后又跳转到登录页面,在提交信息后输出session都是正常的,没有问题,但是页面跳转后,session出现丢失现象,无法正常完成登陆。

通过查找资料,发现原来是bom头的原因。受COOKIE送出机制的限制,在这些文件开头已经有BOM的文件中,COOKIE无法送出(因为在COOKIE送出前PHP已经送出了文件头),所以登入和登出功能失效。一切依赖COOKIE、SESSION实现的功能全部无效。

正确的处理方法是去掉某些文件的bom,一般情况是在入口文件出现的bom问题,我处理的方法是用Notepad++打开文件,格式选择以UTF-8无bom格式编码,然后保存,重新上传到服务器即可。但一定要注意,去掉bom上传到服务器之前需要把服务器上源文件删掉,上传覆盖不能去掉bom。

PS:如果文件是UTF-8编码,则确保所有文件都是UTF-8 不能用UTF-8 + BOM

好了,通过这篇文章,我们就对session跨网页失效的原因和解决方案做了详细的说明。

碰到类似奇怪问题,就迎刃而解了。

如果对PHP的Session使用还有不清楚的地方,可参见之前的文章: