PHP重定向后丢失会话

167

如何在PHP重定向后解决丢失会话的问题?

最近,我遇到了一个非常普遍的问题:重定向后会话丢失。即使在这个网站上搜索,我仍然找不到解决方案(尽管这个已经接近了答案)。

更新

我已经找到了答案,并且想在这里发布它,以帮助任何遇到同样问题的人。


2
问题是如何解决PHP重定向后丢失会话的问题。我已经找到了答案,现在在这里发布,让其他人也知道。因为我的解决方案不在StackOverflow上。 - dayuloli
2
没问题,但这是一个QA网站。请把你的问题写成一个问题。 - jeremy
1
@Aris:http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/ - Dave Chen
30
@Aris 这不是事实,当人们在编码方面有问题时,他们会来到 StackOverflow 寻求帮助。如果没有可用的答案,那么他们就无法获得所需的帮助。我正在尝试提供这个答案。 - dayuloli
由于这是在书中提到的,我的错 :) - Aris
显示剩余6条评论
39个回答

249

首先,进行以下常规检查:

  1. 确保在调用任何会话之前调用了 session_start();。因此,最安全的方法是将它放在页面开头,在任何其他内容之前,在打开的 <?php 声明后立即使用。也请确保在 <?php 声明前没有空格或制表符。
  2. 重定向后,请使用 exit(); 结束当前脚本(其他人还建议使用 session_write_close();session_regenerate_id(true),您也可以尝试这些,但我会使用 exit();
  3. 确保浏览器启用了 cookie。
  4. 确保关闭了 register_globals,您可以在 php.ini 文件和使用 phpinfo() 中检查此设置。参考此处以了解如何关闭该设置。
  5. 确保您没有删除或清空会话。
  6. 确保您在 $_SESSION 超级全局数组中的键未被覆盖。
  7. 确保重定向到相同的域。因此,从 www.yourdomain.com 重定向到 yourdomain.com 不会将会话转发。
  8. 确保您的文件扩展名是 .php(这种错误很常见!)

这些是最常见的错误,但如果它们没有解决问题,问题很可能与您的托管公司有关。如果在本地主机上一切正常,但在远程/测试服务器上不正常,则很可能是此原因。因此,请检查您托管服务提供商的知识库(也可以尝试其论坛等)。像 FatCow 和 iPage 这样的公司需要您指定 session_save_path。例如:

session_save_path('"your home directory path"/cgi-bin/tmp');
session_start();

(用您实际的家目录路径替换“your home directory path”。这通常在您的控制面板(或等效物)内,但您也可以在根目录下创建一个test.php文件并键入以下内容:

<?php echo $_SERVER['SCRIPT_FILENAME']; ?>

'test.php' 前面的部分是您的主目录路径。当然,确保该文件夹实际存在于您的根目录中。 (某些程序在同步时不会上传空文件夹)


10
写得非常好 +1,如果一切都失败了,就使用cookies(随机生成一个字符串并将其存储在数据库中,然后将其作为cookie值使用)。 - Dave Chen
2
在编程中,切换HTTP和HTTPS可能也会出现问题。https://dev59.com/uHRC5IYBdhLWcg3wAcM3 - dev.e.loper
4
注意,从php 5.4.0版本开始,register_globals已被移除,因此它将不再引起问题。 - anthonygore
2
也要检查Web服务器错误日志;在我的情况下,出现了一个错误“无法写入会话数据(文件)。请验证session.save_path的当前设置是否正确”。save_path目录的权限不正确。 - timbonicus
1
确保重定向到相同的域名。因此,从www.yourdomain.com重定向到yourdomain.com不会将会话继续传递。☚解决了我的问题。 - TheTechGuy
显示剩余13条评论

29

在调用头部后,您应该使用 "exit"。

header('Location: http://www.example.com/?blabla=blubb');
exit;

Gecko(例如Waterfox,Firefox,SeaMonkey)存在一个错误,即如果有任何数据输出(例如echo'';)或任何空格,则会完全忽略位置标头。 - John
我不知道不使用exit()会导致如此多的麻烦,但它确实会防止会话被保存。 - Ncoder

24

我尝试了所有可能的解决方案,但都没有成功!当然,我正在使用共享托管服务。

最后,我通过在重定向头中使用“相对URL”来解决了这个问题!

header("location: http://example.com/index.php")

使会话Cookie失效

header("location: index.php")

运作得非常好!


13

我遇到了同样的问题。我花了几个小时来解决它,这让我感到疯狂。

在我的情况下,Chrome和Firefox浏览器中因为缺少favicon.ico而出现了404错误。其他浏览器则没问题。


只是想感谢您的回答,让我意识到 Varnish 将图像的 404 请求转发到 PHP,而没有任何 cookie,因此不断创建新会话。如果没有您,我可能永远都不会发现这个问题。 - Pascal Zajac
1
我曾经遇到过同样的问题,我的favicon.ico被重定向(从子域名到主域名的302重定向),因此每次都会生成一个新的会话。非常感谢! - simdrouin

8

我曾遇到过同样的问题。突然之间,我的一些会话变量无法持续到下一页。问题在于(在 PHP7.1 中)您的头部位置不能带有WWW,例如https://mysite可以,https://www.mysite会丢失该页面的会话变量。不是所有页面都会丢失,只有那一页会。


这是因为www.mysite.com被视为与blog.mysite.com或仅仅的mysite.com完全不同的域名。 - dayuloli
谢谢。这个答案救了我。我已经为这个问题苦恼了两个小时! - Dante

5
当我在header()函数中使用相对路径"dir/file.php"时,它可以正常工作。我认为当你使用完整的URL重定向时,会出现一些原因导致会话未保存...
//Does retain the session info for some reason
header("Location: dir");

//Does not retain the session for some reason
header("Location: https://mywebz.com/dir")

4
我遇到了类似的问题,不过我的情况略有不同。我在一个计算机上进行本地开发,它的主机名是 windows,IP地址为 192.168.56.2
我可以使用下列任意一种方式访问系统: 登录后,我的 PHP 代码会使用以下方式进行重定向:
header('http://windows/');

如果之前用于访问系统的域名不是windows,会导致会话数据丢失。我通过更改代码解决了这个问题:
header('http://'.$_SERVER['HTTP_HOST'].'/');

现在它可以无论用户输入什么本地域名或IP地址都能正常工作。 希望这对某些人有用。

3
我在一个特定的页面遇到了这个问题。我在其他页面设置$_SESSION值,并在重定向之前一切正常。但是这个特定的页面不起作用。
最后我意识到,在这个特定的页面,我在页面开头销毁了会话,但从未重新启动它。因此,我的销毁函数改变为:
function sessionKill(){

    session_destroy();

}

to:

function sessionKill(){

    session_destroy();
    session_start();

}

一切都正常工作了!


3

我为此苦恼了好几天,查看/尝试了所有的解决方案,但我的问题在于重定向后我没有再次调用session_start();。 我只是假设会话仍然“存活”。

所以不要忘记这个细节!


是的!这也是我的问题。我以为启动PHP会话就像为整个房子打开灯一样简单。我没有意识到每进入一个房间都需要打开开关。 - Dale Thompson

2
这让我困扰了很长时间(很高兴找到这篇文章!),但是对于任何仍然无法在页面重定向之间获取会话的人...我必须进入php.ini文件并打开cookie:
session.use_cookies = 1 

我原本认为会话可以在没有cookie的情况下运行...事实上,我知道它们应该可以...但是这至少解决了我的问题,直到我能够理解更大的背景。


我不知道会话可以在没有cookie的情况下工作!每天都学到新东西!http://www.programmerinterview.com/index.php/php-questions/can-sessions-work-without-cookies/ - dayuloli
当然,如果你的配置允许,它们可以在没有cookie的情况下工作。但是你应该知道自己在做什么,并且有一个充分的理由这样做。因为这样会降低安全性。如果出于任何原因必须在没有cookie的情况下工作,那么你至少应该配置ini_set('session.use_strict_mode', '1'),并且通常使用较短的会话时间,在用户登录后使用session_regenerate_id()。但是请注意,如果某个用户在论坛上发布了指向你服务器上网站的链接,那么实际点击此链接的人将接管会话。也许检查IP地址也是一个好主意。 - Michael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接