discuz论坛本身就存在用户窜号的可能性,特别在同一IP下,有大量用户并发访问的情况下。
当接到该项bug反溃的时候,第一想到的方法就是在sid生成时加时间截,然后扩大session表的sid字段长度。但想了一下,虽然加强了,但用户并发大的时间还是会出现。
最后还是直接修改用户session过程:
在class_core.php文件的 discuz_session的init方法中
function init($sid, $ip, $uid) {
$this->old = array('sid' => $sid, 'ip' => $ip, 'uid' => $uid);
$session = array();
if($sid) {
$session = DB::fetch_first("SELECT * FROM ".DB::table('common_session').
" WHERE sid='$sid' AND CONCAT_WS('.', ip1,ip2,ip3,ip4)='$ip'");
}
if(empty($session) || $session['uid'] != $uid) {
$session = $this->create($ip, $uid);
}
$this->var = $session;
$this->sid = $session['sid'];
}
该方法并没有使用到$uid值,这就是窜号的导火线。
下面咱们加强一下该功能:
function init($sid, $ip, $uid) {
$this->old = array('sid' => $sid, 'ip' => $ip, 'uid' => $uid);
$session = array();
if($sid) {
$session = DB::fetch_first("SELECT * FROM ".DB::table('common_session').
" WHERE sid='$sid' AND uid='$uid' AND CONCAT_WS('.', ip1,ip2,ip3,ip4)='$ip'");
}
if(empty($session) || $session['uid'] != $uid) {
$session = $this->create($ip, $uid);
}
$this->var = $session;
$this->sid = $session['sid'];
}
接下来,也修改一下update方法
function update() {
if($this->sid !== null) {
$data = daddslashes($this->var);
if($this->isnew) {
$this->delete();
DB::insert('common_session', $data, false, false, true);
} else {
DB::update('common_session', $data, "sid='$data[sid]'");
}
dsetcookie('sid', $this->sid, 86400);
}
}
加强后:
function update() {
if($this->sid !== null) {
$data = daddslashes($this->var);
if($this->isnew) {
$this->delete();
DB::insert('common_session', $data, false, false, true);
} else {
if($data[uid] < 1){
DB::update('common_session', $data, "sid='$data[sid]'");
}else{
DB::update('common_session', $data, "sid='$data[sid]' AND uid='$data[uid]'");
}
}
dsetcookie('sid', $this->sid, 86400);
}
}
此方法虽然解决的登陆窜号问题,但算不上完美。
原文地址:http://blog.sina.com.cn/s/blog_a82c4d0a01010y7o.html
|