2012-05-09 244 views
11

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

我能够通过不允许浏览器缓存

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

避免这种情况,但这样一来,我失去浏览器缓存的优势。

请提出一个更好的实现方法。我觉得,必须有一种处理这个JavaScript客户端的方式

+5

你不必禁用任何东西。如果他们回去,他们会被提供受限制页面的缓存版本。如果他们试图点击它,则不会有效,因为不会设置适当的会话。 –

+0

@ N.B。一个可能的解决方案可能不一定总是可用,因为用户可能在其显示器上有敏感数据,然后退出。另一个来了(虽然工作站应该被锁定;))并且按下并查看(虽然缓存)了以前用户的数据。我们通常会添加一条提示用户关闭浏览器的信息消息(以确保所有会话都已被清除)。这不一定是最好的方式,但至少您向用户提供了有关潜在问题的信息。 – Juri

+0

如果一切都失败了,便宜的修复方法是在注销的页面上出现“请出于安全原因关闭此窗口”消息。 – izb

回答

10

在PHP中实现而不是JavaScript。

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

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

正如你提到的,在注销,只需取消设置LOGGED_IN会话变量,并摧毁了会议:

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

如果用户点击返现,没有LOGGED_IN会话变量将是可用的,并且页面将不会加载。

+19

我已经实施了这项技术。但按下按钮实际上并不需要服务器。而是从浏览器缓存中呈现后台页面。因此它不会重定向到登录页面。 – piyush

+0

那么问题是什么?注销后用户无法与服务器交互,并且只有后退按钮才能检索他已经看到的数据。如果这些数据可能被其他人滥用,请注意用户关闭窗口或使用匿名标签,如果他不这样做,那是他的错。 – david

0

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

+1

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

0

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

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

由于会话不再有效,“关联某事”将返回一个错误。

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

1

我认为你唯一的服务器端选项是禁止缓存。实际上,如果您正在使用JavaScript大量应用程序,因为您的主要HTML可能只是一系列JS调用,然后即时生成视图,这实际上并不糟糕。这样大量的数据(JS MVC和核心代码)被缓存,但实际的页面请求不是。

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

您可以用

如果这些方法都失败,将被注销页面上的“请关闭这个窗口,出于安全原因”的消息让这一关你的良心一个廉价的修复。 - izb 2012年5月9日在8点36分

但像N.B.说

您不必禁用任何东西。如果他们回去,他们会被提供受限制页面的缓存版本。如果他们试图点击它,则不会有效,因为不会设置适当的会话。 - N.B. 5月9日'12 7:50

0

下面是一个简单而快速的解决方案。

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

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

0

您需要哪个loged在页面中,使用setInterval每1000毫秒,并检查wheather用户登录或不使用AJAX。如果用户会话无效,请将其重定向到登录页面。

3

我面临同样的问题,花了整整一天搞清楚它, 最后纠正它,如下所示:

在登录验证脚本,如果用户进行身份验证设置一个会话值为例说明如下:

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

然后在用户配置文件脚本把下面的代码片段:

<?php 

session_start(); 

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

?> 

上面的代码是什么只和ONL是, y如果$_SESSION['status']设置为"Active"那么只有它会转到用户配置文件,并且只有在用户通过身份验证后,此会话密钥才会被设置为"Active" ... [注意否定['! “在上面的代码片段]

可能退出代码应该如下:

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

希望这有助于... !!!

0

注意,虽然用户无法更改复位会话数据和/或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. 
} 
0

添加在登录HTML页面脚本标签中下面的代码(或任何网页时注销后重定向到)

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

此脚本将在注销后禁用后退按钮。