重定向后 PHP 会话丢失

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

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

更新

我已经找到了答案,我想我会把它贴在这里,以帮助任何人经历同样的问题。

248104 次浏览

首先,进行这些常规检查:

  1. 确保在调用任何会话之前调用了 session_start();。因此,一个安全的做法是将它放在页面的开头,紧接在打开 <?php声明之后,放在其他内容之前。还要确保在打开 <?php声明之前没有空格/制表符。
  2. header重定向之后,使用 exit();结束当前脚本(其他人也建议使用 session_write_close();session_regenerate_id(true),您也可以尝试这些,但是我会使用 exit();)
  3. 确保在用于测试 Cookie 的浏览器中启用 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”之前的位是您的主目录路径。当然,还要确保该文件夹确实存在于根目录中。(有些程序在同步时不上传空文件夹)

这个问题困扰了我很长一段时间(这个帖子很好找!)但是对于那些仍然无法在页面重定向之间进行会话的人来说... ... 我必须进入 php.ini 文件并打开 cookie:

session.use_cookies = 1

我以为会议没有 cookie 也能工作... 事实上,我知道他们应该... 但是这至少解决了我的问题,直到我能理解大局中可能发生的事情。

我也有同样的问题与重定向不工作,并尝试所有的解决方案,我可以找到,我的头重定向正在使用的形式。

我解决这个问题的方法是,将头部重定向放在另一个 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';
}


?>

这不是一个漂亮的解决办法,但它奏效了。

首先销毁旧会话,以确保正确创建了新会话。

session_start();
session_unset();   // remove all session variables
session_destroy(); // destroy the session
session_start();


$_SESSION['username'] = 'username';

是的,session_start()被调用了两次。一次调用 unset 并销毁命令,第二次启动新会话。

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

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

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

使会话 cookie 无效

header("location: index.php")

非常有效!

我也遇到过类似的问题,尽管我所处的环境略有不同。 我在一台主机名为 windows、 IP 地址为 192.168.56.2的机器上进行了本地开发设置。

我可以通过以下任何一种方式进入系统:

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

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

如果以前用于访问系统的域名不是 windows,会话数据将丢失。我解决这个问题的方法是把代码改成:

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

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

我希望这对某人有用。

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

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

而不是 PHP

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

希望这个能帮上忙。

爱情 奶奶

你应该在头调用后使用“ exit”

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

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

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

只是为了记录... 我有这个问题,在几个小时的尝试一切的问题是,磁盘是满的,和 php 会话不能被写入 tmp 目录... 所以如果你有这个问题检查太..。

我在一个特别的页面上碰到了这个问题。在重定向之前,我正在其他页面中设置 $_ SESSION 值,一切正常。但是这个页面不起作用。

最后我意识到,在这个特定的页面中,我正在破坏页面开头的会话,但从未再次启动它。所以我的破坏功能从:

function sessionKill(){


session_destroy();


}

致:

function sessionKill(){


session_destroy();
session_start();


}

一切都成功了!

这几天我一直在纠结这个问题,检查/尝试所有的解决方案,但我的问题是在重定向之后我没有再打电话给 session_start();。我只是假设会议“仍然活着”。

所以别忘了!

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

我也有同样的问题,我花了好几个小时研究它,它快把我逼疯了。

在我的案例中,问题是由于 Chrome 和 Firefox 中的 一个失踪的藏宝图标而调用了404。其他的导航员工作得很好。

在 SO 和其他博客上尝试了许多解决方案之后... ... 对我有效的是添加。访问我的网站根。

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

如果你正在使用 WordPress,我必须添加这个钩子并在 init 上启动会话:

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

如果您使用的是 session_set_cookie_params(),那么您可能需要检查是否将第四个参数 $secure作为 true传递。如果是,则需要使用 https 访问 URL。

$secure参数为 true 意味着 Session 仅在安全请求中可用。这可能比在阶段或生产环境中对您的本地影响更大。

提到它是因为我今天花了大部分时间试图找到这个问题,这就是我解决它的方法。我刚刚被添加到这个项目,没有人提到它需要 https。

因此,您可以在本地使用 https,也可以将 $secure参数设置为 FALSE,然后在本地使用 http。只要确保在您推动更改时将其设置为 true 即可。

根据本地服务器的不同,可能必须在服务器的 httpd-ssl.conf中编辑 DocumentRoot,以便为本地 URL 提供 https。

另一个可能的原因是:

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

成功了! ! !

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

我也有同样的问题。突然之间,我的一些会话变量不能持续到下一个页面。问题是(在 php7.1中)头部位置不能有 WWW,例如 https://mysite。没问题,https://www.mysite。将丢失该页会话变量。不是全部,只有那一页。

对我来说没有什么奏效,但我找到了问题的原因(并解决了它) :

检查浏览器 Cookie,确保没有 不同子域上的 php 会话 cookie(比如一个代表“ Www.website.com”,一个代表“ Website.com”)。

这是由于一个 javascript 错误地使用子域来设置 cookie 并在 iframe 中打开页面造成的。

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

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

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

在@dayuloli 的回答中没有提到的最常见的原因:

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

  2. 会话目录可能不是可写的。您可以用 is_writable(session_save_path())检查它

我也遇到了同样的问题,于是我疯狂地在代码中寻找答案。最后,我发现我的主机最近在我的服务器上更新了 PHP 版本,并且没有正确地在 php.ini文件上设置 session_save_path参数。

因此,如果有人读到这一点,请检查 php.ini配置之前,任何其他。

确保在 session_start()和设置会话时没有调用 session_write_close

session_start();


[...]


session_write_close();


[...]


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

如果您正在使用 Laravel 并且遇到了这个问题,那么您需要在重定向之前保存会话数据。

session()->save();
// Redirect the user to the authorization URL.
header('Location: ' . $authorizationUrl);
exit;
session_start();
error_reporting(E_ALL ^ (E_NOTICE | E_WARNING));
if(!isset($_SESSION['name_session'])){
unset($_SESSION['name_session']);
session_destroy();
}
if(isset($_SESSION['name_session'])){
$username = $_SESSION['name_session'];
}

既然 GDPR 是一个东西,访问这个问题的人可能会使用 cookie 脚本。那个剧本给我带来了麻烦。显然,PHP 使用一个名为 PHPSESSID的 cookie 来跟踪会话。如果那个脚本删除了它,您就会丢失数据。

我用的是 这个 cookie 脚本。它有一个启用“必要”cookie 的选项。我将 PHPSESSID添加到列表中,脚本停止删除 cookie,一切又开始工作了。

您可以启用一些 PHP 设置来避免使用 PHPSESSID,但是如果 Cookie 脚本是问题的原因,为什么不修复 那个呢。

经过多天的调试,我解决了这个问题,这都是因为我从 PayPal Express Checkout 返回的 URL 没有“ www”。Chrome 认识到这些域名应该得到相同的对待,但其他浏览器有时却不是这样。当使用会话/cookie 和绝对路径时,不要忘记“ www”!

通过给 PHP 存储会话文件的路径赋予组写权限,我修复了这个问题。可以使用 session _ save _ path ()函数查找会话路径。

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

ini_set( 'session.cookie_secure', 1 );

发生这种情况是因为实际的项目是通过 http 而不仅仅是 https 来工作的

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

现在回复已经太晚了,但是这对我很有用

对我来说,这是一个权限错误,这解决了它:

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

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

返回文章页面

session_start();


$_SESSION["user"] = 123;


header("Location: session2.php");

返回文章页面

session_start();


print_r($_SESSION);

它正在打印一个空数组。

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

希望这对谁有帮助。

当我在 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")

快速和工作的解决方案为我,只是简单的双重定向。我创建了2个文件: fb-go.phpfb-redirect.php

fb-go.php的样子:

session_start();


$_SESSION['FBRLH_state'] = 'some_unique_string_for_each_call';


header('Location: fb-redirect.php');

和 fb-redirect:

session_start();


header('Location: FULL_facebook_url_with_' . $_SESSION['FBRLH_state'] . '_value');

同样值得一提的是 Android Chrome 浏览器的行为,用户可以在其中看到类似的东西:

Android

如果用户选择 Facebook 应用程序,那么会话就会丢失,因为会话是在 Facebook 浏览器中打开的,而不是存储用户会话数据的 Chrome 浏览器。

OP 没有指定他是否重定向到相同的页面(例如在登录之后) ,因此服务器/浏览器缓存也可能是问题所在

一个简单的解决方案是在 URL 的末尾附加版本号(就像强制执行。CSS 文件刷新)

例如:

header('Location: index.php?v='.time());

因此用户被重定向到一个新页面

domain.com/index.php?v=122234982323

这是我对这个问题的看法,因为我没有看到任何人提到这个案子. 。

如果您的应用程序是通过多个节点上的负载平衡器运行的,那么您不能将会话保存到文件中,或者需要为所有节点共享此路径,否则每个节点将拥有自己的会话文件,您将遇到不一致性。

因此,我重构我的应用程序,使用数据库,而不是文件系统。

关键点

  1. 不要在返回页上启动会话。
  2. 不要使用 session 变量,也不要包含 header.php 这个用户 session 变量
  3. 只要使一个链接到主页或个人资料页后插入付款信息和状态

我的问题与其他人略有不同。

我正在尝试在我的网站上实现 Google oAuth。

我的网站的网址是 website.local,谷歌重定向网址是 127.0.0.1

因为它们不是同一个域,所以创建了两个不同的 session _ id。

验证您的会话不是严格的。如果是,当您返回时,比如从 Stripe 返回时,它将重新生成会话。

使用方法:

ini_set('session.cookie_samesite', 'Lax');

有时候,这个问题涉及到 PHP INI 会话设置,比如没有设置 session.cookie_samesite,或者没有设置为与用例匹配。大多数 cookie/session/security 相关的错误出现在 web 浏览器的开发者控制台/网络日志中(Windows 中的 F12键) ,但是请记住每个 web 浏览器处理事情的方式是不同的。

我有一个网站,不断删除用户会话在微软边缘浏览器,但没有火狐。Edge 中的网络日志显示我的会话 SameSite设置没有设置,在我将 ini_set("session.cookie_samesite", "None");添加到应用程序之前,我并不认为这是一个问题。做出这个更改修复了 Edge 删除我的用户会话的问题。因此,如果您的会话问题出现在一个浏览器与另一个浏览器中,请检查浏览器网络日志中的安全性错误差异。