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