2011-11-07 38 views
0

我编码了我的第一个会话系统。问题如下。有关会议的几个问题

// INDEX.PHP 
    include("db.php"); // this file starts session with session_start(); also changes the default session name 

    if($_POST['login']){ $login = escape($_POST['login']); } 
    if($_POST['password']){ $password = escape($_POST['password']); } 

    if(isset($login) && isset($password)){ // LOGIN ATTEMPT 

    // check for brute force attacks 
    $btime = $time-600; // 10 minutes 
    $pull = $DB->query("SELECT * FROM logins WHERE user='$login' AND time>$btime"); 
    if($DB->num_rows($pull) > 5){ // more than 10 tries in the last 10 minutes 


      $error = "Too many login attempts have been made with this login. "; 
    // maybe lock the account for x hours 

     }else{ 

     // AUTHENTICATE 
     $sql = $DB->query("SELECT * FROM users WHERE user='$login' AND password='$password'"); 
     if($DB->n 

um_rows($sql) == 1){ // AUTHENTICATED 
    $user = $DB->fetch_array($sql); 
    $ok = 1;  
      session_regenerate_id(); 
      $_SESSION['userid'] = $user['id']; 
      $_SESSION['agent'] = md5($_SERVER['HTTP_USER_AGENT']); 
      $_SESSION['idle'] = $time; 
      header("Location: welcome.php"); // REDIRECT TO USER AREA 

    }else{ // NOT AUTHENTICATED 
     $ok = 0; 
     $error = "Wrong pass or login."; 
    } 
    // log all attempts (removed) 
    } 
    } 

功能,检查会话:

function checksession(){ 
    global $DB, $time; 

    if($_SESSION['userid'] > 0){ 

     $userid = intval($_SESSION['userid']); 
     $user = $DB->fetch("SELECT * FROM users WHERE id=$userid"); 
     $idle = $time-$_SESSION['idle']; 

     if(!$user){ header("Location: index.php"); } 
    elseif($_SESSION['agent'] != md5($_SERVER['HTTP_USER_AGENT'])){ session_destroy(); header("Location: ".$site."index.php"); } // check user agent 
    elseif($idle > 7200){ session_destroy(); header("Location: ".$site."index.php"); } // destroy session if no activity for 2 hours 
    else{ 
     $_SESSION['idle'] = $time; 
    } 
    }else{ header("Location: ".$site."index.php"); // user id not set 
    } 
    return $userid; 
} 

注销功能

function logout(){ 
session_destroy(); 
header("Location: index.php"); 
} 

它工作正常,但它并不完美。

问题:

  • 当我做session_regenerate_id();会话ID发生变化,但旧会话仍保持活动状态。所以这非常没用。我在安全级别发生变化时执行此操作。我也考虑过定期做。我正在使用PHP 5.3.6的MAMP。

  • 如果用户不想破坏会话并简单地关闭浏览器,会话文件似乎永远留在系统中。我想知道如何1)使会话在X小时后死亡,即使用户处于活动状态。 2)如果用户闲置会使会话死掉(有点像我现在拥有的系统,但是来自系统的一方)。

  • 我注意到,如果我在修改会话cookie之前登录相同的会话文件,除了使用用户信息的新重新生成的id以外,还会保存在会话文件文件夹(空)中。不知道这个,只是觉得很奇怪。

  • 我是否正确销毁会话?

该网站应该有一个相当高的安全等级,因为真钱会涉及到用户帐户。我正考虑在会话中保存页面点击次数,如果发生更改,则意味着其他人已将会话结束。会议然后将被杀死。

回答

1

session_regenerate_id():会话ID实际上只是大的随机数。 PHP实现它们的会话ID是非常随机的,以防止人们简单地猜测或增加有效的会话ID。尽管如此,如果攻击者获得有效的会话ID,他们可以“劫持”你的会话。更改有效会话的会话标识实际上没有解决这个问题。您需要添加另一层安全性,可能是将客户端的IP地址与会话ID相关联。这样,您几乎可以发布会话ID(不推荐),但是攻击者无法利用它,因为他们无法使用欺骗IP地址完成TCP连接。

如果用户不想破坏会话并简单地关闭浏览器,会话文件似乎永远留在系统中。 会话cookie将保留在客户端计算机上,直到他的浏览器认为它已过期。我认为默认时间是24分钟。会话文件将保留在服务器上,直到它被PHP的会话垃圾收集器收集。

我想知道如何1)使会话在X小时后死亡,即使用户处于活动状态。这可以通过PHP的配置参数来控制:session.gc-maxlifetime。请注意,您还需要更改其他session.gc选项以强制清除。 See this also

这也适用于用户闲置的情况。

编辑:我看错了。这不适用于活跃用户。对于活跃的用户,您必须手动记录他们已登录多久并“注销”。

我注意到,如果我修改会话cookie之前登录相同的会话文件获取保存在会话文件文件夹(空)除了新的重新编号与用户信息我不知道这是什么手段。也许你可以详细说明。

我是否正确销毁会话? 不是。在删除服务器端cookie之前,您还需要尝试强制客户端删除其会话cookie。这是here

作为最后一点,我不确定检查客户端的USER_AGENT是一个好主意,尤其是因为它很容易被欺骗。您应该考虑检查完整(不是散列)的IP地址,因为它需要3次握手。 (请注意,除非您通过SSL进行通信,否则这仍然容易受到MITM攻击)

+0

没有session_regenerate_id():用户可以提交他自己的会话。在其他问题上陷入困境。我选择了用户代理而不是IP,因为IP可以更改。 – domino

+0

“我注意到,如果我修改会话cookie之前登录相同的会话文件获取保存在会话文件文件夹(空)除了新的重新编号与用户信息” - 我的意思是,如果我编辑PHPSESSION cookie然后登录,会话文件与用户提交的名字保存在会话文件夹中。这是空的。 – domino

+0

即使您重新生成,用户也将始终能够提交自己的会话。再生只是给他们一个新的会话ID - 如果他们真的是恶意的,他们会忽略它,并继续与任意会话ID联系。确保会话ID匹配客户端的某个唯一标识符是您的工作。我认为IP地址比用户代理更好,但IP地址将受到MITM攻击,除非您通过SSL。 – jedwards