重定向后PHP会话丢失


131

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

最近,我遇到了一个非常常见的问题,即在重定向后丢失会话。在搜索该网站后,我仍然找不到任何解决方案(尽管是最接近的解决方案)。

更新资料

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


1
问题是如何解决在PHP中重定向后丢失会话的问题。我已经找到答案了,只需将其发布在这里以让其他人知道。因为我的解决方案不在StackOverflow上。
dayuloli 2013年

2
很好,但这是质量检查网站。请问您一个问题。
杰里米

我没注意到那是你的。不过,此站点仅用于提问,而不用于回答您已经知道的问题。
阿里斯


21
@Aris并非如此,当人们对编码有疑问时,他们会向StackOverflow寻求帮助。如果没有可用的答案,那么他们将无法获得所需的帮助。我正在尝试提供答案。
dayuloli 2013年

Answers:


208

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

  1. 确保session_start();在调用任何会话之前已被调用。因此,一个安全的选择就是将其放在页面的开头,即在开始<?php声明之后立即放在其他任何地方。另外,请确保在打开<?php声明之前没有空格/制表符。
  2. 在后header重定向,使用结束当前的脚本exit();(其他人也建议session_write_close();,并session_regenerate_id(true),你可以尝试那些为好,但我会用exit();
  3. 确保在用于对其进行测试的浏览器中启用了cookie。
  4. 确保register_globals已关闭,您可以在php.ini文件上并使用进行检查phpinfo()。有关如何关闭它的信息,请参考
  5. 确保您没有删除或清空会话
  6. 确保您的$_SESSION超全局数组中的密钥不会在任何地方被覆盖
  7. 确保您重定向到相同的域。因此,从重定向www.yourdomain.comyourdomain.com不会继续进行会话。
  8. 确保您的文件扩展名是.php(确实发生了!)

现在,这些是最常见的错误,但是如果他们没有解决问题,那么问题很可能出在您的托管公司身上。如果一切正常,localhost但不能在您的远程/测试服务器上运行,则很可能是罪魁祸首。因此,请检查您的托管服务提供商的知识库(也可以尝试其论坛等)。对于FatCow和iPage之类的公司,它们要求您指定session_save_path。像这样:

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

(将“您的主目录路径”替换为您的实际主目录路径。这通常在控制面板内(或等效菜单中),但是您也可以test.php在根目录上创建一个文件并输入:

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

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


8
写得很好的+1(如果所有操作失败),只需使用cookie(随机生成一个字符串并将其存储在db中,并将其用作您的cookie值)。
戴夫·陈

2
HTTP和n的https之间切换可能也成为一个问题stackoverflow.com/questions/441496/...
dev.e.loper

4
请注意,自php 5.4.0起,register_globals已被删除,因此它将不再引起问题
anthonygore 2014年

2
还要检查网络服务器错误日志;在我的情况下,出现错误“无法写入会话数据(文件)。请验证session.save_path的当前设置正确”。save_path目录上的权限错误。
timbonicus 2014年

为什么将我的会话存储在session.save_path以外的任何地方?
贾斯汀

26

您应该在标题调用后使用“退出”

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

Gecko有一个错误(例如Waterfox,Firefox,SeaMonkey),如果有任何数据输出(例如echo ' ';)或任何类型的空白,它将完全忽略位置标头。
John

18

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

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

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

取消会话Cookie

header("location: index.php")

像魅力一样运作!


7

我有同样的问题。我工作了几个小时,这让我发疯。

就我而言,问题是由于仅在Chrome和Firefox中缺少favicon.ico而调用了404 。其他导航器工作正常。


只是想感谢您的回答,让我意识到Varnish将404个图像请求转发到了PHP,而没有任何cookie,因此不断创建新的会话。没有你,可能永远都想不通。
Pascal Zajac

我遇到了同样的问题,我的favicon.ico正在重定向(从子域到主域的302重定向),因此每次都生成一个新会话。非常感谢!
simdrouin

4

当我在header()函数中使用相对路径“ dir / file.php”对我有用。我认为当您使用完整网址进行重定向时,由于某种原因,会话未保存...

//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")

3

这让我困扰了很长时间(这篇文章很棒!),但是对于仍然无法在页面重定向之间进行会话的其他人来说,我不得不进入php.ini文件并打开cookie。 :

session.use_cookies = 1 

我以为没有cookie的会议就可以了...事实上,我知道它们应该...但是,这至少解决了我的问题,直到我了解了大局。


我不知道没有cookie的会话就无法工作!每天学些新东西!programmerinterview.com/index.php/php-questions/...
dayuloli

当然,它们可以不使用cookie而工作取决于您的配置。但是你应该知道你在做什么。并且有这样做的充分理由。因为它不太安全。并且如果您出于任何原因必须工作而没有Cookie。您至少应配置ini_set('session.use_strict_mode','1'); 并且通常会话时间较短,并且在用户登录后使用session_regenerate_id()。但是请注意,如果某些用户在论坛中发布指向您服务器上站点的链接,则实际单击此链接的人员将接管该会话。也许检查ip也是一个好主意。
迈克尔

3

我有一个类似的问题,尽管我的情况略有不同。我在一台主机名为windowsIP地址为的机器上进行了本地开发192.168.56.2

我可以使用以下任一方式访问系统:

登录后,我的PHP代码将使用以下方式重定向:

header('http://windows/');

如果不是用于访问系统的先前域名windows,则会话数据将丢失。我将代码更改为:

header('http://'.$_SERVER['HTTP_HOST'].'/');

现在,无论用户输入什么本地域名或IP地址,它都可以工作。

我希望这可能对某人有用。


3

我在一个特定页面上遇到了这个问题。我在重定向之前在其他页面中设置了$ _SESSION值,并且一切正常。但是此特定页面无法正常工作。

最终,我意识到在这个特定页面中,我在页面开始时销毁了该会话,但是再也没有启动它。所以我的销毁功能从:

function sessionKill(){

    session_destroy();

}

至:

function sessionKill(){

    session_destroy();
    session_start();

}

一切正常!


3

我遇到了同样的问题。突然有些会话变量将无法持续到下一页。问题是(在php7.1中)标头位置不能包含WWW,例如https:// mysite。可以,https://www.mysite。将丢失该页面会话变量。并非全部,仅此页面。


那是因为www.mysite.com被视为与blog.mysite.com或完全不同的领域mysite.com
dayuloli

2

我已经为此苦苦挣扎了好几天,一直在检查/尝试所有解决方案,但是我的问题是session_start();重定向后我没有再打来电话。我只是假设会议“还活着”。

所以不要忘记!


是! 这也是我的问题。我以为开始一个PHP会话就像打开整个房子的灯。我没有意识到您必须为进入的每个房间都打开开关。
戴尔·汤普森

1

我遇到了同样的问题,找到了最简单的方法。我只是使用1行JS重定向到了一个.html重定向文件

<!DOCTYPE html>
<html>
<script type="text/javascript">
<!--
window.location = "admin_index.php";
//–>
</script>
</html>

代替PHP

header_remove();
header('Location: admin_login.php');
die;

我希望这有帮助。

爱克


1

如果您正在使用session_set_cookie_params(),则可能要检查是否将第四个参数传递$securetrue。如果是,则需要使用https访问该URL。

$securePARAM是真正的手段会议仅仅是一个安全的请求中提供。这可能比在舞台或生产环境中对本地的影响更大。

提到它是因为我今天大部分时间都在尝试查找此问题,而这正是为我解决的问题。我只是被添加到该项目中,没有人提到它需要https。

因此,您既可以在本地使用https,也可以将$secure参数设置为FALSE,然后在本地使用http。只需在向上推送更改时将其设置为true即可。

根据您的本地服务器,您可能必须在服务器的中进行编辑DocumentRoothttpd-ssl.conf以便为您的本地URL提供https。


1

另一个可能的原因:

那是我的服务器存储空间。我的服务器磁盘空间已满。因此,我在服务器中删除了一些文件和文件夹并进行了尝试。

它的工作!

我将会话保存在AWS Dynamo DB中,但仍希望服务器中有一些空间来处理会话。不知道为什么!


1

如果您正在使用Laravel并遇到此问题,则需要在重定向之前保存会话数据。

session()->save();
// Redirect the user to the authorization URL.
header('Location: ' . $authorizationUrl);
exit;

0

我也遇到了相同的问题,即重定向无法正常工作,并尝试了所有可以找到的解决方案,我的标头重定向已以某种形式使用。

我通过将标头重定向放置在其他php页面“ signin_action.php”中并通过将所需的变量参数传递给url参数,然后以“ signin_action.php”的形式重新分配它们来解决了该问题。

signin.php

if($stmt->num_rows>0) {
$_SESSION['username'] = $_POST['username'];
echo '<script>window.location.href = "http://'.$root.'/includes/functions/signin_action.php?username='.$_SESSION['username'].'";</script>';
error_reporting(E_ALL);

signin_action.php

<?php
require('../../config/init.php');
$_SESSION['username'] = $_GET['username'];
if ($_SESSION['username']) {

echo '<script>window.location.href = "http://'.$root.'/user/index.php";</script>';
exit();
} else {
echo 'Session not set';
}

?>

这不是一个很好的解决方法,但它确实有效。


0

对我来说,错误是我试图在会话中保存一个无法序列化的对象,以便在尝试编写会话时抛出异常。但是由于我所有的错误处理代码都已停止任何操作,所以我从未看到此错误。

我可以在Apache错误日志中找到它。


0

只是为了记录...我遇到了这个问题,经过数小时的尝试之后,问题是磁盘已满,并且无法将php会话写入tmp目录...因此,如果您有此问题,请检查太...


这个答案对我有用。我们使用nginx运行Amazon Machine Image。会话文件夹不归正确的用户所有(在我们的情况下www),这似乎是一个错误,因此chown -R www.www对会话文件夹执行操作可以解决此问题。
约书亚

0

对我来说,Firefox已将会话ID(PHPSESSID)存储在cookie中,但是Google Chrome使用了GET或POST参数。因此,您只需要确保返回的脚本(对我来说:paypal checkout)在url或POST参数中提交PHPSESSID。


0

在SO和其他博客上尝试了许多解决方案之后...对我有用的是在我的网站根目录中添加.htaccess。

RewriteEngine on
RewriteCond %{HTTP_HOST} ^yoursitename.com$
RewriteRule ^.*$ "http\:\/\/www\.yoursitename\.com" [R=301,L]

0

如果您使用的是Wordpress,则必须添加此钩子并在init上启动会话:

function register_my_session() {
    if (!session_id()) {
        session_start();
    }
}
add_action('init', 'register_my_session');

0

对我没有任何帮助,但我发现了导致问题的原因(并已解决):

检查您的浏览器cookie,并确保不同子域上没有php会话cookie(例如,一个用于“ www.website.com ”,一个用于“ website.com ”)。

这是由于JavaScript错误地使用了子域来设置Cookie并在iframe中打开页面所致。


0

首先,请确保session_start()在使用$_SESSION变量之前正在调用。

如果您已禁用错误报告,请尝试打开并查看结果。

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

@dayuloli的答案中未提及的最常见原因:

  1. 磁盘空间问题。确保磁盘空间未满,需要一些空间来存储会话文件。

  2. 会话目录可能不可写。你可以用is_writable(session_save_path())


0

我遇到了同样的问题,我很疯狂地在我的代码中寻找答案。最终,我发现托管服务器最近更新了服务器上的PHP版本,并且未正确设置文件上的session_save_path参数php.ini

因此,如果有人阅读此内容,请先检查php.iniconfig。


0

确保在设置会话session_write_close之间session_start()以及设置会话时未调用它。

session_start();

[...]

session_write_close();

[...]

$_SESSION['name']='Bob'; //<-- won't save

0

既然GDPR是一回事,访问此问题的人们可能会使用Cookie脚本。好吧,那个脚本对我造成了问题。显然,PHP使用了一个名为PHPSESSID来跟踪会话。如果该脚本将其删除,则会丢失数据。

我使用了这个cookie脚本。它具有启用“基本” cookie的选项。我添加PHPSESSID到列表中,脚本停止删除cookie,并且一切再次开始工作。

您可能可以启用某些PHP设置来避免使用PHPSESSID,但是如果您的Cookie脚本是问题的原因,为什么不解决该问题


0

经过数天的调试,我解决了这个问题,这是因为我的来自PayPal Express Checkout的返回URL没有“ www”。Chrome认识到应该对域进行相同的处理,但其他浏览器有时则不一样。使用会话/ cookie和绝对路径时,请不要忘记“ www”!


0

我通过为组授予对PHP存储会话文件的路径的写权限进行修复。您可以使用session_save_path()函数找到会话路径。


0

今天,我在一个项目中遇到了这个问题,我不得不将此参数更改为false(或删除这些行,默认情况下是禁用的):

ini_set( 'session.cookie_secure', 1 );

发生这种情况是因为实际项目通过HTTP而不是仅通过https运行。在文档http://php.net/manual/en/session.security.ini.php中找到了更多信息


0
ini_set('session.save_path',realpath(dirname($_SERVER['DOCUMENT_ROOT']) . '/../session'));
session_start();

回复太晚了,但这对我有用


0

对我来说,这是权限错误,并解决了这个问题:

chown -R nginx:nginx / var / opt / remi / php73 / lib / php / session

我已经在PHP上测试了几个小时,最后一次测试是我创建了两个文件session1.php和session2.php。

session1.php:

session_start();

$_SESSION["user"] = 123;

header("Location: session2.php");

session2.php:

session_start();

print_r($_SESSION);

它正在打印一个空数组。

在这一点上,我认为这可能是服务器问题,实际上是。

希望这对某人有帮助。


1
chown是一个BAD解决方案,因为它将在软件包更新时变回默认值。请参阅默认池配置(www.conf)中的注释。正确的方法是使用apache以外的其他目录(例如:/ var / lib / php / nginx / session)
Remi Collet

你是对的。软件包更新首先是我遇到问题的原因。但这是完成的方式,因此我需要一些快速的解决方案,这有所帮助。我的SYS管理员解决了它,我对Linux不太满意。
temo
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.