无法隔离PHP

时间:2015-08-07 09:14:54

标签: php jquery

我有一个PHP应用程序,它在登录MYSQL表时存储了用户的会话ID,当用户注销并通过注销过程销毁它们的会话时,该表被删除。如果MYSQL表在该session_id列中仍有值,则不允许用户再次登录。这在自然触发的注销的情况下非常有用。但是,当用户只是关闭浏览器窗口/选项卡时,似乎服务器保留了会话变量,而且由于未调用自然的logout.php,MySQL表中的session_id列也没有被清空。因此,我可以在同一台计算机上输入受登录保护的任何URL,然后直接进入。这是一个安全问题 - 由不遵循自然退出指令的用户触发而不仅仅是关闭浏览器窗口。

我已经关注SO thread here并试图使用onbeforeunload()JS函数来处理浏览器关闭的这种情况。如您所知,当发生这4个事件中的任何一个时,onbeforeunload()事件被触发 - (1)浏览器关闭(2)通过单击""从页面导航到另一个页面。链接(3)刷新页面(4)提交表格。

在下面的代码中,我在(1)和(3)中遇到以下问题,我很难搞清楚: 问题1.当我关闭浏览器窗口时,我会通过" Stay On the Page"和"离开Page"选项。但是,对于 call_my_special_script.php 的AJAX调用正在两个选项上发生,而在"留在页面上时不应该发生这种情况。 call_my_special_script.php 只是删除MySQL表中session_id的内容。 问题2.当我刷新浏览器时 - Safari / IE代码说什么都不应该发生,但是当我不期待它时,我会看到警报。无论我在警报上选择了什么,它都会调用 call_my_special_script.php 并删除session_id值。

我应该在这里做些什么来解决这些问题?

<script>
 var validNavigation = false;

  function browserCloseEvents() {

  var dont_confirm_leave = 0;   
  var leave_message = 'You sure you want to leave the page?'
  function goodbye(e) {

 if (!validNavigation) {
  if (dont_confirm_leave!==1) {
    if(!e) e = window.event;
    e.cancelBubble = true;
    e.returnValue = leave_message;
    if (e.stopPropagation) {
      e.stopPropagation();
      e.preventDefault();
    }
    $.ajax({
        type: 'GET',
        url: "call_my_special_script.php",
        async: false,
        success: function () {
            alert("sucess");
        }
     });
    return leave_message;
     }   
   }
  }                                                                                                                          

  window.onbeforeunload = goodbye;
  $(document).bind('keypress', function(e) {
   if (e.keyCode == 116){
    validNavigation = true;
    }
   });

  $("a").bind("click", function() {
    validNavigation = true;
  });

$("form").bind("submit", function() {
  validNavigation = true;
});

 $("input[type=submit]").bind("click", function() {
  validNavigation = true;
 });

}   

$(document).ready(function() {
  browserCloseEvents();
});

2 个答案:

答案 0 :(得分:0)

与往常一样,您应该从不将应用程序的安全性建立在某些客户端功能上。因为它们可以()轻松绕过。

在您的情况下,您可以将会话时间设置为 15分钟并且在用户登录时只需发送一个AJAX信标请求以重置该计时器每隔5分钟说 15分钟内登录的时间跨度。之后他必须重新登录,因为他的会话已经过期。

我见过各种CMS使用这种技术。

你也可以像其他一些AJAX调用一样捎带其他请求来查看新消息..等等。就像 StackOverflow 那样。

答案 1 :(得分:0)

我不会做什么,为什么

在我看来,在这种情况下你根本不应该依赖JavaScript,原因如下:

  • 首先可能会禁用JavaScript。
  • 整个页面上只需要一个JS错误就可以禁用“注销例程”。
  • 浏览器可能会崩溃。
  • 无法可靠告知用户是否实际离开了您的网页。
    您还必须考虑大量的浏览器和操作系统行为。

    示例:

    • 如果我在两个标签页中打开您的页面并仅关闭其中一个标签,我仍然会退出。
    • 在Mac上点击 F5 不会做任何事情(至少在Chrome中)。但如果我在你的页面上这样做,它会认为我正在重新加载它,并禁用了注销例程。然后,我可以愉快地继续关闭标签而不会退出。
    • 在Windows上按 Ctrl R 或在Mac Cmd R 重新加载Chrome中的某个页面,但您的网站会在执行此操作时将其注销。
    • 点击 Del 在Windows上的大多数浏览器中浏览一页。最后一页可能在您的网站上,也可能不在您的网站上,但无论如何我都会退出。

另外,我认为这是非常糟糕的做法:

  

如果MYSQL表在该session_id列中仍有值,则不允许用户再次登录。

我看到人们试图以“安全理由”来证明这一点,但它确实没有添加任何内容。

如果有攻击者窃取了您的用户名和密码,则会阻止他们在您登录时登录,但这也会阻止同时他们他们已登录!
(如果有人有你的密码,安全性早就被破坏了。)

如果他们偷了你的会话cookie,它根本不会保护你。

当你登录设备1并希望登录设备2时,它唯一能做的就是惹恼你。

我会做什么

  1. 让用户随时重新登录,覆盖旧会话。
  2. 将数据库中的会话与到期时间戳相关联 超过该时间戳后,将不再接受会话cookie,用户必须再次登录 根据您的需要,您可以使用“登录时间+ 2小时”或“上次看到的时间+ 15分钟”(您必须在每次加载页面时更新,等等)。
  3. 没有为会话cookie设置明确的截止日期,因此根据PHP的setcookie功能,当浏览器关闭时, 将被删除。
    有些浏览器可能不会这样做,但这就是数据库过期的原因。
  4. (如果你想阻止会话劫持:) 将数据库中的会话与用户的IP相关联 如果会话cookie匹配,但IP不匹配,则用户必须再次登录。
  5. A(有点贵)替代

    告知用户何时“离开”的最简单方法是,如果您有一个打开的连接,当用户离开时该连接将关闭。
    这是 HTTP(S)的情况 - 它基于后续请求 但是,对于WebSockets

    现在,想法是:

    • 当用户加载页面时,会打开一个WebSocket。
    • 浏览器每10秒钟(或左右)向服务器发送一条消息。
    • 只要为用户打开至少一个WebSocket,并且它在过去30秒(或左右)内发布了一条消息,用户就会保持登录状态,否则会丢弃其会话。

    对于较旧的浏览器,您可以添加一个AJAX回退,这也可以,但比WebSockets产生更多的流量。

    上升空间:

    • 攻击者的机会窗口大幅减少。
    • 多个标签不再是问题。

    缺点:

    • 产生相当多的流量。
    • 当用户失去与服务器的连接时,即使他们没有关闭浏览器,也会将用户注销。