1

下面的问题是一个安全问题。只要用户的浏览器打开,我就使用 Sessions 来保持用户登录到我的网站。

现在我保持用户登录的 php 代码非常简单。当用户登录时,我首先使用用户名创建会话(authentication.php):

if (($row['user'] == $usr)&&($row['value'] == $pwd)) {
    $response = "ok";
    session_start();
    $_SESSION['name'] = $usr;
    break;
}

然后我从每个页面创建对 JavaScript 的调用以检查用户是否存在我将网页(AJAX)更改为看起来好像用户已登录(显示在标题欢迎中),JavaScript 如下所示:

function checkUserExistance(data,size)
{
    var xmlhttp;

    if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp=new XMLHttpRequest();
    } else {// code for IE6, IE5
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }

    xmlhttp.onreadystatechange=function()
    {
        if (xmlhttp.readyState==4 && xmlhttp.status==200) {
            var response = xmlhttp.responseText;           
            document.getElementById("title").value = response;
        }
    }

    xmlhttp.open("POST",url + page,true);

    xmlhttp.send();
}

现在在服务器端检查用户是否已登录,我使用以下简单函数,JavaScript 正在调用该函数:

session_start();
if (isset($_SESSION['user'])) {
    echo $_SESSION['name'];
}

现在我的问题很简单,就是这样的正确方法吗?只要浏览器打开就保持用户身份验证,因为如果我做对了,JavaScript 就在客户端,这意味着每个人都可以更改它并跳过服务器端在页面上发表评论的检查。

我的解决方案是在发布评论时添加另一个检查是在服务器端检查用户是否有一个打开的会话但是用户可以假装是另一个已经过身份验证的用户,这太令人沮丧了......我错过了什么应该我愿意?

4

1 回答 1

2

尽管您可能希望在生产中使用已建立的安全框架,但如果您试图了解经典安全会话管理的原理,那么您在这里的理解并不遥远。重要的是检查站点中每个页面顶部的会话数据,以确保用户没有跳过登录检查。

从用于管理会话的服务器发回的 cookie 将保存在浏览器的内存中。在从任何页面发送任何用户内容之前,首先检查用户是否已登录(会话变量中是否有用户名)。如果为空,则用户未登录,因此您将他们发送到登录页面,询问他们的用户名/密码组合;

在此处输入图像描述

还要记住,保存在服务器内存中的会话状态对进程回收没有弹性,也不会在负载平衡的网络场上按预期工作。

任何类型的后续浏览器请求、XMLHTTP、HTML、JPG 都将包含此 cookie,您可以在服务器端使用它来检查会话。因此,例如,您在此处所做的工作将起作用,因为服务器使用 cookie 来绑定您的会话。只要您的 cookie 不是“可猜测的”,这在很大程度上就是用户名/密码身份验证系统的工作方式。

在此处输入图像描述

我想说,你真的不需要对 XMLHTTP 做任何事情,除非你想让会话保持更长的时间。通常,服务器会在几分钟后过期 cookie(可配置)。

因此,对于穷人的安全系统,总结一下;

  1. 每个浏览器请求,检查 $_SESSION['user'],如果它是空的,直接到登录页面。
  2. 在登录页面上,检查用户名/密码匹配(读者练习:))如果是,将用户名存储在会话中(这将自动返回 cookie)

基本上就是这样。每次都会发送浏览器 cookie,只要您每次收到请求时都不要忘记检查,就可以了。这以及许多其他原因是使用框架很好的原因,但我认为在这里理解基础知识很有用。

其他要记住的事情;

首先,您应该只检查服务器端的安全性。您不能在客户端 javascript 中执行此操作。其次,您需要为每个请求执行此操作。浏览器每次都会发送一个 cookie,只要它与您之前检查的用户名/密码匹配的会话变量就可以了。如果没有 cookie,或者 cookie 相关的会话变量不包含您之前设置的用户变量,则用户没有登录,您应该再次将他们重定向到登录页面。您对每个请求都执行此操作。

请记住,您的 AJAX 调用仍然是一个请求,因此也必须在服务器端进行相同的登录检查。最简单的做法是在 PHP 中而不是在客户端 javascript 中设置页面标题,但是如果您想使其成为 ajax 客户端,那么您需要处理由于上述原因服务器可能拒绝您的请求的可能性并且将您重定向到登录页面不会是您期望从 XMLHTTTPRequest 获得的响应。因此,至少您需要更复杂的错误处理,充其量您可以将您的登录过程重写为仅 AJAX。

这是服务器的一些伪代码;

if session(name) is empty then
    if IsAjaxRequest then
        send ajax access denied response code and exit
    else
        redirect browser to login page
    endif
else
    if IsAjaxRequest then
         send ajax data // eg. title
    else
         send html page (injecting session(name) into title)
    endif
endif

那就是说。我不会写那个伪代码。我会使用不同的端点(页面)来提供浏览器 HTML 响应和 AJAX API 响应,但希望您能大致了解您的选择是什么。

于 2013-07-02T10:03:04.643 回答