154

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

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

更新

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

4

38 回答 38

237

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

  1. 确保session_start();在调用任何会话之前调用。因此,一个安全的选择是将其放在页面的开头,紧接在开头<?php声明之后,然后再放在其他任何地方。<?php还要确保在开始声明之前没有空格/制表符。
  2. 重定向后header,使用结束当前脚本exit();(其他人也建议使用session_write_close();and session_regenerate_id(true),您也可以尝试这些,但我会使用exit();
  3. 确保在您用于测试的浏览器中启用了 cookie。
  4. 确保register_globals已关闭,您可以在php.ini文件上进行检查,也可以使用phpinfo(). 有关如何将其关闭的信息,请参阅此内容。
  5. 确保您没有删除或清空会话
  6. 确保您的$_SESSION超全局数组中的键在任何地方都没有被覆盖
  7. 确保您重定向到同一个域。因此,从 a 重定向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' 之前的位是您的主目录路径。当然,请确保该文件夹确实存在于您的根目录中。(部分程序同步时不上传空文件夹)

于 2013-06-21T18:49:34.457 回答
27

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

header('Location: http://www.example.com/?blabla=blubb');
exit;
于 2015-06-02T12:48:34.753 回答
22

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

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

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

使会话 cookie 无效

header("location: index.php")

像魅力一样工作!

于 2015-03-31T21:12:00.970 回答
9

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

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

于 2016-05-05T11:37:52.633 回答
6

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

于 2017-02-23T11:24:09.177 回答
5

当我在对我有用的 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")
于 2019-07-29T00:58:22.530 回答
4

我遇到了类似的问题,尽管我的上下文略有不同。windows我在主机名和 IP 地址为的机器上进行了本地开发设置192.168.56.2

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

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

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

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

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

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

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

于 2015-04-10T13:36:38.353 回答
3

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

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

function sessionKill(){

    session_destroy();

}

至:

function sessionKill(){

    session_destroy();
    session_start();

}

一切正常!

于 2016-02-08T04:03:17.477 回答
2

这让我困惑了很长时间(这篇文章很容易找到!)但是对于仍然无法在页面重定向之间进行会话的其他任何人......我不得不进入 php.ini 文件并打开 cookie :

session.use_cookies = 1 

我认为会话在没有 cookie 的情况下可以正常工作……事实上我知道他们应该……但这至少解决了我的问题,直到我能够理解大局中可能发生的事情。

于 2014-05-09T16:53:12.580 回答
1

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

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

而不是 PHP

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

我希望这有帮助。

爱克

于 2015-05-04T10:06:21.430 回答
1

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

所以不要忘记这一点!

于 2016-03-07T12:01:20.243 回答
1

如果您正在使用session_set_cookie_params(),您可能需要检查是否将第四个参数$secure作为true. 如果是,那么您需要使用 https 访问该 url。

$secure参数为真意味着会话仅在安全请求中可用。这可能比在舞台或生产环境中对您的本地影响更大。

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

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

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

于 2016-11-28T22:01:49.103 回答
1

另一个可能的原因:

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

成功了!!!

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

于 2017-01-27T12:27:04.300 回答
1

没有什么对我有用,但我找到了导致问题的原因(并解决了它):

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

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

于 2017-04-10T06:11:30.407 回答
1
ini_set('session.save_path',realpath(dirname($_SERVER['DOCUMENT_ROOT']) . '/../session'));
session_start();

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

于 2019-03-28T09:15:09.387 回答
1

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

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);

它正在打印一个空数组。

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

希望这可以帮助某人。

于 2019-04-08T11:09:11.437 回答
1

关键点

  1. 不要在返回页面上启动会话。
  2. 不要使用会话变量并且不包含 header.php 哪个用户会话变量
  3. 插入付款信息和状态后,只需链接到主页或个人资料页面
于 2020-09-29T19:33:26.023 回答
0

我也遇到了重定向不起作用的相同问题,并尝试了我能找到的所有解决方案,我的标头重定向正在以一种形式使用。

我通过将标头重定向放在不同的 php 页面“signin_action.php”中并通过我想要的 url 参数传递变量参数然后以“signin_action.php”形式重新分配它们来解决它。

登录.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';
}

?>

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

于 2014-10-11T14:32:39.083 回答
0

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

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

于 2015-11-06T14:35:19.170 回答
0

只是为了记录......我遇到了这个问题,经过几个小时的尝试,问题是磁盘已满,php会话无法写入tmp目录......所以如果你有这个问题,请检查也...

于 2015-11-30T15:18:56.180 回答
0

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

于 2016-03-11T00:41:26.707 回答
0

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

RewriteEngine on
RewriteCond %{HTTP_HOST} ^yoursitename.com$
RewriteRule ^.*$ "http\:\/\/www\.yoursitename\.com" [R=301,L]
于 2016-05-17T12:18:44.723 回答
0

如果您使用的是 Wordpress,我必须添加这个钩子并在初始化时启动会话:

function register_my_session() {
    if (!session_id()) {
        session_start();
    }
}
add_action('init', 'register_my_session');
于 2016-11-24T16:39:37.090 回答
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())

于 2017-12-08T13:45:22.560 回答
0

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

所以,如果有人读到这个,请先检查php.ini配置。

于 2018-02-07T17:43:31.173 回答
0

确保在设置会话session_write_close之间session_start()和设置会话时不调用。

session_start();

[...]

session_write_close();

[...]

$_SESSION['name']='Bob'; //<-- won't save
于 2018-02-13T15:53:24.770 回答
0

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

session()->save();
// Redirect the user to the authorization URL.
header('Location: ' . $authorizationUrl);
exit;
于 2018-02-24T06:57:12.153 回答
0

既然 GDPR 是一回事,访问这个问题的人可能会使用 cookie 脚本。好吧,那个脚本给我带来了问题。显然,PHP 使用一个名为 cookiePHPSESSID来跟踪会话。如果该脚本将其删除,您将丢失数据。

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

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

于 2018-05-23T10:15:50.553 回答
0

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

于 2018-07-30T20:28:29.167 回答
0

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

于 2018-10-24T12:32:41.567 回答
0

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

ini_set( 'session.cookie_secure', 1 );

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

于 2019-03-07T09:04:00.470 回答
0

对我来说快速且有效的解决方案只是简单的双重重定向。我创建了 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 重定向:

session_start();

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

另外值得一提的是 Android Chrome 浏览器行为。用户可以在哪里看到类似的东西:

安卓

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

于 2019-08-11T13:22:36.057 回答
0

OP 没有指定他是否重定向到同一页面(例如登录后),如果这样,服务器/浏览器缓存也可能是问题

一个简单的解决方法是在 URL 的末尾附加版本号(就像强制 .CSS 文件刷新时一样)

例子:

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

因此用户被重定向到被视为新页面的页面

domain.com/index.php?v=122234982323
于 2019-08-30T18:54:29.503 回答
0

这是我在这个问题上的 2 美分,因为我没有看到有人提到这个案例。

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

所以我正在重构我的应用程序以使用数据库而不是文件系统。

于 2020-03-19T19:39:58.610 回答
0

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

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

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

由于它们不是同一个域,因此创建了两个不同的 session_id。

于 2021-10-25T13:46:25.000 回答
0

验证您的会话不是严格的。如果是,当你回来时,就像从 Stripe 回来一样,它会重新生成会话。

用这个:

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

于 2022-01-08T04:49:06.783 回答
-2
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'];
    }
于 2018-03-26T12:06:20.730 回答
-5

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

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

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

是的,session_start()被调用了两次。一次调用 unset 和 destroy 命令,第二次调用新会话。

于 2014-11-12T19:32:23.747 回答