我编写了我的第一个会话系统。问题如下。
// 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更改,但旧的ID也保持活动状态。所以这很没用。我在安全级别更改时执行此操作。我也考虑过定期做。我在php 5.3.6中使用MAMP。
如果用户不想破坏会话并只是关闭浏览器,则会话文件似乎永远留在系统中。我想知道如何在X小时后使会话死亡,即使用户处于活动状态。 2)如果用户空闲,会话会死(有点像我现在的系统,但是来自系统方面)。
我注意到,如果我在登录之前修改了会话cookie,那么除了带有用户信息的新重新生成的id之外,会在会话文件文件夹(空)中保存。不确定这个,只是觉得很奇怪。
我是否正确销毁了会话?
该网站应具有相当高的安全级别,因为真实资金将涉及用户帐户。我正在考虑在会话中保存页面点击次数,当它发生变化时,意味着其他人已经完成了会话。会议将被杀死。
答案 0 :(得分:1)
session_regenerate_id():会话ID实际上只是大型随机数。 PHP实现其会话ID非常随机,以防止人们简单地猜测或增加有效的会话ID。尽管如此,如果攻击者获得有效的会话ID,他们可以“劫持”您的会话。更改有效会话的会话ID实际上无法解决此问题。您需要添加另一层安全性,可能是通过将客户端的IP地址与会话ID相关联。这样,您几乎可以发布会话ID(不推荐),但是攻击者无法利用它,因为他们无法使用欺骗性IP地址完成TCP连接。
如果用户不想破坏会话并只是关闭浏览器,则会话文件似乎永远留在系统中。 会话cookie将保留在客户端计算机上,直到他的浏览器认为它已过期。我认为默认时间是24分钟。会话文件将保留在服务器上,直到被PHP的会话垃圾收集器收集。
我想知道如何1)在X小时后使会话死亡,即使用户处于活动状态。这可以通过PHP的配置参数来控制:session.gc-maxlifetime。请注意,您还需要更改其他session.gc选项以强制清除。 See this also
如果用户空闲,这也适用。
编辑:我读错了。这不适用于活动用户。对于活跃用户,您必须手动跟踪他们登录的时间并“注销”。我注意到如果我在登录之前修改了会话cookie,那么除了使用用户信息的新重新生成的ID 之外,会在会话文件文件夹(空)中保存该文件我是不知道这意味着什么。也许你可以详细说明。
我是否正确销毁了会话? 并不是的。在删除服务器端cookie之前,您还需要尝试强制客户端删除其会话cookie。这是here。
作为最后一点,我不确定检查客户端的USER_AGENT是个好主意,特别是因为它很容易欺骗。您应该考虑检查完整(非散列)IP地址,因为它需要3次握手。 (请注意,除非您通过SSL进行通信,否则仍然容易受到MITM攻击)