【问题标题】:Prevent back button after logout注销后防止返回按钮
【发布时间】:2012-05-17 17:17:42
【问题描述】:

我不希望用户在注销后通过单击返回按钮返回到受保护的页面。在我的注销代码中,我正在取消设置会话并重定向到登录页面。但是,我认为浏览器正在缓存页面,因此尽管会话从注销中被破坏,它仍然可见。

我可以通过不允许浏览器缓存来避免这种情况

header("Cache-Control", "no-cache, no-store, must-revalidate")

但是这样我就失去了浏览器缓存的优势。

请提出一个更好的方法来实现这一点。我觉得,javascript客户端一定有办法处理这个问题

【问题讨论】:

  • 您不必禁用任何东西。如果他们返回,则会为他们提供受限制页面的缓存版本。如果他们试图点击它,什么都不会起作用,因为不会设置适当的会话。
  • @N.B.一种可能的解决方案可能不一定总是可用,因为用户可能在他的显示器上有敏感数据然后注销。另一个过来(尽管工作站应该被锁定;))并按下并查看(尽管缓存)前一个用户的数据。我们通常会添加一条信息消息,提醒用户关闭浏览器(只是为了确保所有会话都已清除)。这不一定是最好的方法,但至少您向用户提供了有关潜在问题的信息。
  • 如果所有其他方法都失败了,一个廉价的修复方法是在注销页面上显示“出于安全原因请关闭此窗口”消息。

标签: php javascript jquery


【解决方案1】:

在 PHP 而不是 javascript 中实现这一点。

在每个页面的顶部,检查用户是否登录。如果没有,他们应该被重定向到登录页面:

<?php 
      if(!isset($_SESSION['logged_in'])) : 
      header("Location: login.php");  
?>

正如您提到的,在注销时,只需取消设置 logged_in 会话变量,然后销毁会话:

<?php
      unset($_SESSION['logged_in']);  
      session_destroy();  
?>

如果用户现在点击返回,logged_in 会话变量将不可用,页面将不会加载。

【讨论】:

  • 我已经实现了这种技术。但是点击后退按钮实际上并不向服务器请求。相反,后页是从浏览器缓存中呈现的。因此它不会重定向到登录页面。
  • 那么问题出在哪里?用户在注销后无法与服务器交互,并且使用后退按钮他只能检索他已经看到的数据。如果这些数据可能被其他人滥用,请通知用户关闭窗口或使用匿名选项卡,如果他不这样做,那是他的错。
  • 用户登录并查看一些敏感数据。然后他退出并离开计算机。其他人出现,按下后退按钮并可以访问敏感数据。这就是问题所在。
【解决方案2】:

我也遇到了同样的问题,花了一整天的时间来解决这个问题, 最后整改如下:

如果用户通过身份验证,则在登录验证脚本中设置一个会话值,例如:

$_SESSION['status']="Active";

然后在用户配置文件脚本中输入以下代码 sn-p:

<?php

session_start();

if($_SESSION['status']!="Active")
{
    header("location:login.php");
}

?>

以上代码的作用是,只有且仅当 $_SESSION['status'] 设置为 "Active" 时,它才会转到用户配置文件,并且只有当用户通过身份验证时,此会话密钥才会设置为 "Active"... [注意否定['! '] 上面的代码 sn -p]

大概注销代码应该如下:

{
    session_start();
    session_destroy();
    $_SESSION = array();
    header("location:login.php");
}

希望这会有所帮助...!!!

【讨论】:

    【解决方案3】:

    这是我在我的应用程序中使用的一个简单的解决方案。

    在登录 HTML 页面(或注销后重定向到的任何页面)的脚本标记内添加以下代码

    <script>
        history.pushState(null, null, null);
        window.addEventListener('popstate', function () {
            history.pushState(null, null, null);
        });
    </script>
    

    它将禁用后退按钮。您将无法通过单击返回按钮返回。

    注意:未在 Safari 上测试。

    【讨论】:

    • 这里是什么document.title
    • 嗨 Vijju,无论您在 head 标签中给出什么,Javascript 都会获取页面的标题。您可以将其设为 null,它将按照上述问题的要求工作。
    • 我已经编辑了答案并在我的应用程序中进行了测试。工作正常。
    • HII @Mashmoom 。我还有一个疑问,那就是当我打开登录页面并单击后退按钮时,它不会返回主页。当用户从网站注销时,只有后退按钮被禁用。剩余时间它可以工作
    • 我明白了。你的意思是通常如果一个人进入登录页面,那么后退按钮需要工作,但只有在注销后它才会被禁用 ryt?我能想到的是有另一个登录页面,看起来像同一个登录。但只有在注销时,它才会进入第二个注销页面,其中包含上面的脚本。
    【解决方案4】:

    我认为您唯一的服务器端选项是禁止缓存。如果您使用的是 Javascript 繁重的应用程序,这实际上并没有那么糟糕,因为您的主要 HTML 可能只是一系列 JS 调用,然后动态生成视图。这样一来,大部分数据(JS MVC 和核心代码)都被缓存了,但实际的页面请求却没有。

    要添加到下面粘贴的 cmets,我建议在加载期间添加一个小的 AJAX 调用,即使缓存页面会触发到您的后端并检查会话。如果未找到会话,它将重定向用户。这是客户端代码,当然不是安全修复,但看起来更好。

    你可以从良心上摆脱它

    如果所有其他方法都失败了,一个廉价的修复方法是在已注销的页面上显示“出于安全原因请关闭此窗口”消息。 – izb 2012 年 5 月 9 日 8:36

    但就像 N.B.说

    您不必禁用任何东西。如果他们返回,则会为他们提供受限制页面的缓存版本。如果他们试图点击它,什么都不会起作用,因为不会设置适当的会话。 – 注意2012 年 5 月 9 日 7:50

    【讨论】:

      【解决方案5】:

      您可以在每个受限页面上插入条件/函数,检查是否设置了适当的会话变量。这样,您可以打印 2 个版本的页面(一个用于有效用户,一个用于重定向到登录页面)

      【讨论】:

      • 我已经实现了这个。但它不会阻止用户在单击后退按钮时呈现页面,因为它是从浏览器的缓存中呈现的。虽然,如果用户刷新页面或在页面上执行任何操作,他将被重定向回登录页面。由于内页中的个人信息可能很少,我想限制用户在注销后通过点击返回按钮来查看以前的页面。
      【解决方案6】:

      避免用户返回不是一个很好的理由,最重要的是根本不安全。

      如果您在网站上的每个“管理员”操作之前测试用户的会话,您应该没问题,即使用户点击后退按钮,看到缓存页面并尝试某些操作。

      由于会话不再有效,“关系”将返回错误。

      相反,您应该专注于拥有一个真正安全的后台。

      【讨论】:

        【解决方案7】:

        这是一个简单快捷的解决方案。

        在登录表单标签中添加target="_blank",它在不同的窗口中显示内容。然后在注销后只需关闭该窗口并解决后退按钮问题(Safari 浏览器)。

        即使尝试使用历史记录也不会显示页面,而是重定向到登录页面。这对于 Safari 浏览器来说很好,但对于 Firefox 等其他浏览器,session_destroy(); 会处理它。

        【讨论】:

          【解决方案8】:

          您需要登录的页面,每 1000 毫秒使用一次setInterval,并检查用户是否已登录或未使用 ajax。如果用户会话无效,将他重定向到登录页面。

          【讨论】:

            【解决方案9】:

            请注意,尽管用户在重置会话数据和/或 cookie 后无法更改任何内容,但他们仍然可以看到登录用户在上次访问时可以访问的常规信息。这是由于浏览器缓存页面造成的。

            您必须确保在登录用户可访问的每个页面上添加标题,告诉浏览器数据是敏感的,他们不应该缓存后退按钮的脚本结果。重要的是添加

            header("Cache-Control: no-cache, must-revalidate");
            

            请注意,除了此标头下脚本的直接结果之外的其他元素仍将被缓存,您可以从中受益。看到您逐渐加载部分页面并使用此标头标记敏感数据和主要 HTML。

            正如答案所暗示的,取消设置$_SESSION 全局变量的logged_in 部分可以实现注销,但请注意,首先,您不需要像PHP's session_destroy() documentation 中提到的那样销毁会话

            注意:您不必从常规代码中调用 session_destroy()。清理 $_SESSION 数组而不是销毁会话数据。

            其次,您最好不要破坏会话,正如文档中的下一个警告所解释的那样。

            另外,unset() 是一个惰性函数;这意味着它不会应用效果,直到下一次使用有问题的(部分)变量。在敏感情况下使用赋值立即生效是一种很好的做法,主要是可以在并发请求中使用的全局变量。我建议你改用这个:

            $_SESSION['logged_in'] = null;
            

            并让垃圾收集器收集它,同时它作为登录用户无效。

            最后,完成解决方案,这里有一些功能:

            <?php
            /*
             * Check the authenticity of the user
             */
            function check_auth()
            {
               if (empty($_SESSION['logged_in']))
               {
                  header('Location: login.php');
                  // Immediately exit and send response to the client and do not go furthur in whatever script it is part of.
                  exit();
               }
            }
            
            /*
             * Logging the user out
             */
            function logout()
            {
               $_SESSION['logged_in'] = null;
               // empty($null_variable) is true but isset($null_variable) is also true so using unset too as a safeguard for further codes
               unset($_SESSION['logged_in']);
               // Note that the script continues running since it may be a part of an ajax request and the rest handled in the client side.
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2023-02-21
              • 1970-01-01
              • 2011-05-14
              • 2020-06-04
              • 2014-10-22
              • 1970-01-01
              • 2016-02-06
              • 2013-07-20
              相关资源
              最近更新 更多