【问题标题】:PHP session lost after redirect重定向后PHP会话丢失
【发布时间】:2013-06-19 00:06:12
【问题描述】:

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

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

更新

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

【问题讨论】:

  • 问题是如何解决PHP中重定向后丢失会话的问题。我已经想出了答案,只是在这里发布让其他人知道。因为我的解决方案不在 StackOverflow 上。
  • 没关系,但这是一个 QA 站点。请提出您的问题。
  • 我没注意到是你发的。不过,这个网站是用来提问的,而不是用来回答你已经知道的问题的。
  • @Aris 这不是真的,当人们对编码有疑问时,他们会来 StackOverflow 寻求帮助。如果没有可用的答案,那么他们就无法获得所需的帮助。我正在尝试提供这个答案。

标签: php session redirect session-cookies shared-hosting


【解决方案1】:

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

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

【讨论】:

  • 写得很好+1,如果都失败了,就用cookies(随机生成一个字符串并存储在数据库中,作为你的cookie值)。
  • http 和 https 之间的切换也可能是个问题stackoverflow.com/questions/441496/…
  • 请注意,从 php 5.4.0 开始,register_globals 已被移除,因此不会再造成问题
  • 也检查网络服务器错误日志;就我而言,出现错误“无法写入会话数据(文件)。请验证 session.save_path 的当前设置是否正确”。 save_path 目录的权限错误。
  • 我的会话将存储在 session.save_path 以外的其他地方的任何原因?
【解决方案2】:

你应该在 header-call 之后使用“exit”

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

【讨论】:

  • Gecko(例如 Waterfox、Firefox、SeaMonkey)存在一个错误,如果有任何数据输出(例如 echo ' ';)或任何类型的空白,它将完全忽略位置标头。跨度>
【解决方案3】:

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

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

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

使会话 cookie 无效

header("location: index.php")

工作就像一个魅力!

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

    • 只是想感谢您的回答,让我意识到 Varnish 将 404 个图像请求转发到 PHP 没有任何 cookie,因此不断创建新会话。没有你,可能永远都想不通。
    • 我遇到了同样的问题,我的 favicon.ico 正在被重定向(从子域到主域的 302 重定向),因此每次都会生成一个新会话。非常感谢!
    【解决方案5】:

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

    【讨论】:

    • 这是因为www.mysite.com 被视为与blog.mysite.com 或简单的mysite.com 完全不同的域
    • 谢谢。这个答案救了我。我一直在努力解决这个问题两个小时!
    【解决方案6】:

    当我在对我有用的 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")
    

    【讨论】:

      【解决方案7】:

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

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

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

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

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

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

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

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

      【讨论】:

        【解决方案8】:

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

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

        function sessionKill(){
        
            session_destroy();
        
        }
        

        到:

        function sessionKill(){
        
            session_destroy();
            session_start();
        
        }
        

        一切正常!

        【讨论】:

          【解决方案9】:

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

          session.use_cookies = 1 
          

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

          【讨论】:

          • 我不知道会话可以在没有 cookie 的情况下工作!每天学些新东西! programmerinterview.com/index.php/php-questions/…
          • 当然,它们可以在没有 cookie 的情况下工作,这取决于您的配置。但是你应该知道你在做什么。并且有充分的理由这样做。因为它的安全性较低。并且以防万一您不得不在没有 cookie 的情况下工作。您至少应该配置 ini_set('session.use_strict_mode', '1');并且通常会话时间很短,并且在用户登录后使用 session_regenerate_id()。但是请注意,如果某些用户在论坛中发布指向您服务器上某个站点的链接,则实际单击此链接的人将接管会话。也许检查 ip 也是一个好主意。
          【解决方案10】:

          我遇到了同样的问题并找到了最简单的方法。 我只是用 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;
          

          我希望这会有所帮助。

          爱 克

          【讨论】:

            【解决方案11】:

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

            所以别忘了!

            【讨论】:

            • 是的!这也是我的问题。我认为开始一个 PHP 会话就像为整个房子打开一盏灯。我没有意识到你必须为你进入的每个房间打开开关。
            【解决方案12】:

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

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

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

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

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

            【讨论】:

              【解决方案13】:

              另一个可能的原因:

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

              成功了!!!

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

              【讨论】:

                【解决方案14】:

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

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

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

                【讨论】:

                • 还要检查不同文件夹上是否没有多个 cookie - 这就是我的问题所在。如果您手动设置会话 cookie,就会发生这种情况,就像我使用此处给出的解决方案为会话 cookie 设置 SameSite 一样:stackoverflow.com/a/60341320/649497。一旦我在 Set-Cookie 中添加了 path=/,就解决了多个 cookie 的问题。
                【解决方案15】:
                ini_set('session.save_path',realpath(dirname($_SERVER['DOCUMENT_ROOT']) . '/../session'));
                session_start();
                

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

                【讨论】:

                • 这解决了我的问题。总而言之:ini_set('session.cookie_samesite', 'Strict'); ini_set('session.cookie_secure', 1); ini_set('session.use_strict_mode', 1); ini_set('session.save_path',realpath(dirname($_SERVER['DOCUMENT_ROOT']) . '/../session'));
                【解决方案16】:

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

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

                它正在打印一个空数组。

                此时,我认为这可能是服务器问题,事实上确实如此。

                希望这对某人有所帮助。

                【讨论】:

                • chown 是一个糟糕的解决方案,因为它会在包更新时改回默认值。请参阅默认池配置 (www.conf) 中的 cmets。如果使用 apache 目录以外的其他目录(例如:/var/lib/php/nginx/session)
                • 你是对的。包更新首先是我的问题的原因。但因为这是完成的方式,我需要一些快速的解决方案,这有帮助。我的 SYS 管理员解决了这个问题,我对 Linux 不太熟悉。
                【解决方案17】:

                关键点

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

                【讨论】:

                  【解决方案18】:

                  我也遇到了同样的问题,重定向不起作用,并尝试了我能找到的所有解决方案,我的标头重定向正在表单中使用。

                  我通过将标头重定向放在不同的 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';
                  }
                  
                  ?>
                  

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

                  【讨论】:

                    【解决方案19】:

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

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

                    【讨论】:

                      【解决方案20】:

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

                      【讨论】:

                      • 这个答案对我有用。我们使用 nginx 运行 Amazon 系统映像。会话文件夹不属于正确的用户(在我们的例子中为 www)似乎存在错误,因此在会话文件夹上执行 chown -R www.www 可以解决问题。
                      【解决方案21】:

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

                      【讨论】:

                        【解决方案22】:

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

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

                        【讨论】:

                          【解决方案23】:

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

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

                          【讨论】:

                            【解决方案24】:

                            首先,确保在使用$_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())查看它

                            【讨论】:

                              【解决方案25】:

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

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

                              【讨论】:

                                【解决方案26】:

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

                                session_start();
                                
                                [...]
                                
                                session_write_close();
                                
                                [...]
                                
                                $_SESSION['name']='Bob'; //<-- won't save
                                

                                【讨论】:

                                  【解决方案27】:

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

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

                                  【讨论】:

                                    【解决方案28】:

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

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

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

                                    【讨论】:

                                      【解决方案29】:

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

                                      【讨论】:

                                        【解决方案30】:

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

                                        【讨论】:

                                          猜你喜欢
                                          • 1970-01-01
                                          • 1970-01-01
                                          • 2017-04-06
                                          • 2014-08-14
                                          相关资源
                                          最近更新 更多