如何解决 PHP 重定向后会话丢失的问题?
最近遇到了一个很常见的重定向后会话丢失的问题。在通过这个网站搜索后,我仍然找不到解决方案(尽管这是最接近的)。
更新
我找到了答案,我想我会在这里发布它以帮助遇到同样问题的任何人。
如何解决 PHP 重定向后会话丢失的问题?
最近遇到了一个很常见的重定向后会话丢失的问题。在通过这个网站搜索后,我仍然找不到解决方案(尽管这是最接近的)。
更新
我找到了答案,我想我会在这里发布它以帮助遇到同样问题的任何人。
首先,执行以下常规检查:
session_start();
在调用任何会话之前调用。因此,一个安全的选择是将其放在页面的开头,紧接在开头<?php
声明之后,然后再放在其他任何地方。<?php
还要确保在开始声明之前没有空格/制表符。header
,使用结束当前脚本exit();
(其他人也建议使用session_write_close();
and session_regenerate_id(true)
,您也可以尝试这些,但我会使用exit();
)register_globals
已关闭,您可以在php.ini
文件上进行检查,也可以使用phpinfo()
. 有关如何将其关闭的信息,请参阅此内容。$_SESSION
超全局数组中的键在任何地方都没有被覆盖www.yourdomain.com
到yourdomain.com
不会继续会话。.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' 之前的位是您的主目录路径。当然,请确保该文件夹确实存在于您的根目录中。(部分程序同步时不上传空文件夹)
您应该在标头调用后使用“退出”
header('Location: http://www.example.com/?blabla=blubb');
exit;
我尝试了所有可能的解决方案,但没有一个对我有用!当然,我使用的是共享托管服务。
最后,我通过在重定向标头中使用“相对 url”解决了这个问题!
header("location: http://example.com/index.php")
使会话 cookie 无效
header("location: index.php")
像魅力一样工作!
我有同样的问题。我为此工作了几个小时,这让我发疯了。
就我而言,问题是由于仅在 Chrome 和 Firefox 中缺少 favicon.ico而调用了 404 。其他导航器工作正常。
我遇到了同样的问题。突然之间,我的一些会话变量不会持续到下一页。问题原来是(在 php7.1 中)你的标题位置不能有 WWW,例如https://mysite。没关系,https://www.mysite。将丢失该页面会话变量。不是全部,只是那个页面。
当我在对我有用的 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")
我遇到了类似的问题,尽管我的上下文略有不同。windows
我在主机名和 IP 地址为的机器上进行了本地开发设置192.168.56.2
。
我可以使用以下任一方式访问系统:
登录后,我的 PHP 代码将使用以下命令重定向:
header('http://windows/');
如果之前用于访问系统的域名不是windows
,会话数据将会丢失。我通过将代码更改为:
header('http://'.$_SERVER['HTTP_HOST'].'/');
现在,无论用户输入什么本地域名或 IP 地址,它都可以正常工作。
我希望这可能对某人有用。
我在一个特定的页面上遇到了这个问题。在重定向之前,我在其他页面中设置了 $_SESSION 值,一切正常。但是这个特定的页面不起作用。
最后我意识到,在这个特定的页面中,我在页面的开头破坏了会话,但再也没有启动它。所以我的销毁功能从:
function sessionKill(){
session_destroy();
}
至:
function sessionKill(){
session_destroy();
session_start();
}
一切正常!
这让我困惑了很长时间(这篇文章很容易找到!)但是对于仍然无法在页面重定向之间进行会话的其他任何人......我不得不进入 php.ini 文件并打开 cookie :
session.use_cookies = 1
我认为会话在没有 cookie 的情况下可以正常工作……事实上我知道他们应该……但这至少解决了我的问题,直到我能够理解大局中可能发生的事情。
我有同样的问题,并找到了最简单的方法。我只是用 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;
我希望这有帮助。
爱克
我已经为此苦苦挣扎了好几天,检查/尝试了所有解决方案,但我的问题是重定向后我没有session_start();
再次调用。我只是假设会话“还活着”。
所以不要忘记这一点!
如果您正在使用session_set_cookie_params()
,您可能需要检查是否将第四个参数$secure
作为true
. 如果是,那么您需要使用 https 访问该 url。
$secure
参数为真意味着会话仅在安全请求中可用。这可能比在舞台或生产环境中对您的本地影响更大。
提到它是因为我今天大部分时间都在试图找到这个问题,这就是为我解决它的原因。我刚刚被添加到这个项目中,没有人提到它需要 https。
因此,您可以在本地使用 https,也可以将$secure
参数设置为FALSE
然后在本地使用 http。只需确保在推送更改时将其设置回 true 即可。
根据您的本地服务器,您可能必须DocumentRoot
在httpd-ssl.conf
服务器中进行编辑,以便为您的本地 url 提供 https。
另一个可能的原因:
那是我的服务器存储空间。我的服务器磁盘空间已满。因此,我删除了服务器中的几个文件和文件夹并进行了尝试。
成功了!!!
我将会话保存在 AWS Dynamo DB 中,但它仍然希望我的服务器中有一些空间来处理会话。不知道为什么!!!
没有什么对我有用,但我找到了导致问题的原因(并解决了它):
检查您的浏览器 cookie 并确保不同子域上没有 php 会话 cookie(例如“ www.website.com ”和“ website.com ”一个)。
这是由于 javascript 错误地使用子域来设置 cookie 并在 iframe 中打开页面造成的。
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。
session1.php:
session_start();
$_SESSION["user"] = 123;
header("Location: session2.php");
session2.php:
session_start();
print_r($_SESSION);
它正在打印一个空数组。
在这一点上,我认为这可能是服务器问题,事实上,它是。
希望这可以帮助某人。
关键点
我也遇到了重定向不起作用的相同问题,并尝试了我能找到的所有解决方案,我的标头重定向正在以一种形式使用。
我通过将标头重定向放在不同的 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';
}
?>
这不是一个漂亮的解决方法,但它确实有效。
对我来说,错误是我试图在会话中保存一个不可序列化的对象,以便在尝试编写会话时引发异常。但是由于我所有的错误处理代码都已经停止了任何操作,所以我从来没有看到错误。
不过,我可以在 Apache 错误日志中找到它。
只是为了记录......我遇到了这个问题,经过几个小时的尝试,问题是磁盘已满,php会话无法写入tmp目录......所以如果你有这个问题,请检查也...
对我来说,Firefox 已将会话 ID (PHPSESSID) 存储在 cookie 中,但 Google Chrome 已使用 GET 或 POST 参数。因此,您只需确保返回脚本(对我来说:paypal checkout)在 url 或 POST 参数中提交 PHPSESSID。
在 SO 和其他博客上尝试了许多解决方案之后……对我有用的是将 .htaccess 添加到我的网站根目录。
RewriteEngine on
RewriteCond %{HTTP_HOST} ^yoursitename.com$
RewriteRule ^.*$ "http\:\/\/www\.yoursitename\.com" [R=301,L]
如果您使用的是 Wordpress,我必须添加这个钩子并在初始化时启动会话:
function register_my_session() {
if (!session_id()) {
session_start();
}
}
add_action('init', 'register_my_session');
首先,确保session_start()
在使用$_SESSION
变量之前调用。
如果您禁用了错误报告,请尝试打开并查看结果。
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
@dayuloli 的回答中未提及的最常见原因:
磁盘空间问题。确保您的磁盘空间未满,您需要一些空间来存储会话文件。
会话目录可能不可写。你可以检查它is_writable(session_save_path())
我遇到了同样的问题,我疯狂地在我的代码中寻找答案。最后我发现我的主机最近更新了我服务器上的 PHP 版本,并且没有正确设置文件上的session_save_path
参数php.ini
。
所以,如果有人读到这个,请先检查php.ini
配置。
确保在设置会话session_write_close
之间session_start()
和设置会话时不调用。
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;
既然 GDPR 是一回事,访问这个问题的人可能会使用 cookie 脚本。好吧,那个脚本给我带来了问题。显然,PHP 使用一个名为 cookiePHPSESSID
来跟踪会话。如果该脚本将其删除,您将丢失数据。
我使用了这个 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。在文档http://php.net/manual/en/session.security.ini.php中找到更多信息
对我来说快速且有效的解决方案只是简单的双重重定向。我创建了 2 个文件:fb-go.php
和fb-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,它正在存储用户会话数据。
OP 没有指定他是否重定向到同一页面(例如登录后),如果这样,服务器/浏览器缓存也可能是问题
一个简单的解决方法是在 URL 的末尾附加版本号(就像强制 .CSS 文件刷新时一样)
例子:
header('Location: index.php?v='.time());
因此用户被重定向到被视为新页面的页面
domain.com/index.php?v=122234982323
这是我在这个问题上的 2 美分,因为我没有看到有人提到这个案例。
如果您的应用程序通过多个节点上的负载均衡器运行,则您无法将会话保存到文件中或需要为所有节点共享此路径,否则每个节点将拥有自己的会话文件,您将遇到不一致的情况。
所以我正在重构我的应用程序以使用数据库而不是文件系统。
我的问题与其他问题略有不同。
我正在尝试在我的网站上实施 Google oAuth。
我网站的开发网址是website.local
,谷歌重定向网址是127.0.0.1
。
由于它们不是同一个域,因此创建了两个不同的 session_id。
验证您的会话不是严格的。如果是,当你回来时,就像从 Stripe 回来一样,它会重新生成会话。
用这个:
ini_set('session.cookie_samesite', 'Lax');
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'];
}
首先销毁旧会话,确保正确创建新会话。
session_start();
session_unset(); // remove all session variables
session_destroy(); // destroy the session
session_start();
$_SESSION['username'] = 'username';
是的,session_start()
被调用了两次。一次调用 unset 和 destroy 命令,第二次调用新会话。