我不希望用户在注销后通过单击返回按钮返回到安全页面。在我的注销代码中,我正在取消设置会话并重定向到登录页面。但是,我认为浏览器正在缓存页面,因此尽管会话从注销中被破坏,它仍然可见。
我可以通过不允许浏览器缓存来避免这种情况
header("Cache-Control", "no-cache, no-store, must-revalidate")
但是这样我就失去了浏览器缓存的优势。
请提出一个更好的方法来实现这一点。我觉得,javascript客户端必须有一种处理方法
我不希望用户在注销后通过单击返回按钮返回到安全页面。在我的注销代码中,我正在取消设置会话并重定向到登录页面。但是,我认为浏览器正在缓存页面,因此尽管会话从注销中被破坏,它仍然可见。
我可以通过不允许浏览器缓存来避免这种情况
header("Cache-Control", "no-cache, no-store, must-revalidate")
但是这样我就失去了浏览器缓存的优势。
请提出一个更好的方法来实现这一点。我觉得,javascript客户端必须有一种处理方法
在 PHP 而不是 javascript 中实现这一点。
在每个页面的顶部,检查用户是否登录。如果没有,他们应该被重定向到登录页面:
<?php
if(!isset($_SESSION['logged_in'])) :
header("Location: login.php");
?>
正如您所提到的,在注销时,只需取消设置 logged_in 会话变量,然后销毁会话:
<?php
unset($_SESSION['logged_in']);
session_destroy();
?>
如果用户现在单击返回,则没有可用的 logged_in 会话变量,并且页面将不会加载。
我遇到了同样的问题,花了一整天的时间来解决它,最后纠正如下:
如果用户通过身份验证,则在登录验证脚本中设置一个会话值,例如如下:
$_SESSION['status']="Active";
然后在用户配置文件脚本中放入以下代码片段:
<?php
session_start();
if($_SESSION['status']!="Active")
{
header("location:login.php");
}
?>
上面的代码所做的是,只有且仅当$_SESSION['status']
设置"Active"
为时才会转到用户配置文件,并且"Active"
只有当用户通过身份验证时,此会话密钥才会设置为... [注意否定 ['!'] 在上面的代码片段中]
大概注销代码应该如下:
{
session_start();
session_destroy();
$_SESSION = array();
header("location:login.php");
}
希望这可以帮助...!!!
这是我在我的应用程序中使用的一个简单的解决方案。
在登录 HTML 页面(或注销后重定向到的任何页面)的脚本标记内添加以下代码
<script>
history.pushState(null, null, null);
window.addEventListener('popstate', function () {
history.pushState(null, null, null);
});
</script>
它将禁用后退按钮。您将无法通过单击返回按钮返回。
注意:未在 Safari 上测试。
我认为您唯一的服务器端选项是禁止缓存。如果您使用的是 Javascript 繁重的应用程序,这实际上并没有那么糟糕,因为您的主要 HTML 可能只是一系列 JS 调用,然后动态生成视图。这样一来,大部分数据(JS MVC 和核心代码)都被缓存了,但实际的页面请求却没有。
要添加到下面粘贴的评论,我建议在加载期间添加一个小的 AJAX 调用,即使缓存页面会触发到您的后端并检查会话。如果未找到会话,它将重定向用户。这是客户端代码,不是安全修复,当然,但看起来更好。
你可以用
如果所有其他方法都失败了,一个廉价的修复方法是在注销页面上显示“出于安全原因请关闭此窗口”消息。– izb 2012 年 5 月 9 日 8:36
但就像NB说的
您不必禁用任何东西。如果他们返回,则会为他们提供受限制页面的缓存版本。如果他们试图点击它,什么都不会起作用,因为不会设置适当的会话。– 注意 2012 年 5 月 9 日 7:50
您可以在每个受限页面上插入条件/函数,检查是否设置了适当的会话变量。这样,您可以打印 2 个版本的页面(一个用于有效用户,一个用于重定向到登录页面)
避免用户返回不是一个很好的理由,最重要的是根本不安全。
如果您在网站上的每个“管理员”操作之前测试用户的会话,即使用户点击后退按钮,看到缓存页面并尝试某些操作,您也应该没问题。
由于会话不再有效,“关系”将返回错误。
相反,您应该专注于拥有一个真正安全的后台。
这是一个简单快捷的解决方案。
在登录表单标签中添加target="_blank"
在不同窗口中显示内容的标签。然后在注销后只需关闭该窗口并解决后退按钮问题(Safari 浏览器)。
即使尝试使用历史记录也不会显示该页面,而是重定向到登录页面。这对于 Safari 浏览器来说很好,但对于 Firefox 等其他浏览器来说session_destroy();
,它会处理它。
您需要登录的页面,setInterval
每 1000 毫秒使用一次,并检查用户是否已登录或未使用 ajax。如果用户会话无效,将他重定向到登录页面。
请注意,尽管用户在重置会话数据和/或 cookie 后无法更改任何内容,但他们仍然可以看到登录用户在上次访问时可以访问的常规信息。这是由浏览器缓存页面引起的。
您必须确保在登录用户可访问的每个页面上添加标题,告诉浏览器数据是敏感的,他们不应该缓存后退按钮的脚本结果。重要的是添加
header("Cache-Control: no-cache, must-revalidate");
请注意,除了此标头下脚本的直接结果之外的其他元素仍将被缓存,您可以从中受益。看到您逐渐加载部分页面并使用此标头标记敏感数据和主要 HTML。
正如答案所暗示的那样,取消设置全局变量的logged_in
一部分$_SESSION
可以实现注销,但请注意,首先,您不需要像PHPsession_destroy()
文档中提到的那样销毁会话
注意:您不必从常规代码中调用 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.
}