[原创]uchome登陆机制分析

uchome_ROOT/为uchome的根目录
第一步:
定位到uchome_ROOT/source/do_login.php,找到如下函数:
//同步获取用户源
if(!$passport = getpassport($username, $password)) {
showmessage('login_failure_please_re_login', 'do.php?ac='.$_SCONFIG['login_action']);
}

上示函数便是登陆的第一步处理函数,再次定位:

uchome_ROOT/source/function_common.php,找到如下函数:
//获取用户数据
function getpassport($username, $password) {
global $_SGLOBAL, $_SC;

$passport = array();
if(!@include_once S_ROOT.'./uc_client/client.php') {
showmessage('system_error');
}

$ucresult = uc_user_login($username, $password);
if($ucresult[0] > 0) {
$passport['uid'] = $ucresult[0];
$passport['username'] = $ucresult[1];
$passport['email'] = $ucresult[3];
}
return $passport;
}

至此,我们可以发现现在开始和uc_client相关函数关联了.我们进入uc_client文件夹,开始分析,定位至:uchome_ROOT/uc_client/client.php
/**
* 用户登陆检查
*
* @param string $username 用户名/uid
* @param string $password 密码
* @param int $isuid 是否为uid
* @param int $checkques 是否使用检查安全问答
* @param int $questionid 安全提问
* @param string $answer 安全提问答案
* @return array (uid/status, username, password, email)
数组第一项
1 : 成功
-1 : 用户不存在,或者被删除
-2 : 密码错
*/
function uc_user_login($username, $password, $isuid = 0, $checkques = 0, $questionid = '', $answer = '') {
$isuid = intval($isuid);
//define('UC_API_FUNC', UC_CONNECT == 'mysql' ? 'uc_api_mysql' : 'uc_api_post');
$return = call_user_func(UC_API_FUNC, 'user', 'login', array('username'=>$username, 'password'=>$password, 'isuid'=>$isuid, 'checkques'=>$checkques, 'questionid'=>$questionid, 'answer'=>$answer));
return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
}

因为是mysql,故,UC_API_FUNC的值为uc_api_mysql,通过call_user_func()函数,将参数传给uc_api_mysql(),下面进入最关键的函数了:
uchome_ROOT/uc_client/client.php => uc_api_mysql()
/**
* MYSQL 方式取指定的模块和动作的数据
*
* @param string $model 请求的模块
* @param string $action 请求的动作
* @param string $args 参数(会加密的方式传送)
* @return mix
*/

function uc_api_mysql($model, $action, $args=array()) {
//$model = 'user',$action= 'login',
//$args = Array ( [username] => test2 [password] => test [isuid] => 0 [checkques] => 0 [questionid] => [answer] => )
global $uc_controls;
if(empty($uc_controls[$model])) {
//UC_ROOT uc_client/
include_once UC_ROOT.'./lib/db.class.php';
include_once UC_ROOT.'./model/base.php';
include_once UC_ROOT."./control/$model.php";
eval("$uc_controls['$model'] = new {$model}control();");
//uc_client/control/user.php,usercontrol()类(继承至base基类)实例化
}
if($action{0} != '_') {
$args = uc_addslashes($args, 1, TRUE);
$action = 'on'.$action;//onlogin,usercontrol()中的方法,可以考虑改造此函数以实现预定功能
$uc_controls[$model]->input = $args;//base.php,base基类的方法
//return Array ( [0] => 3 [1] => test2 [2] => test [3] => test@12.com [4] => 0 )

return $uc_controls[$model]->$action($args);//返回预定数组,供调用函数分析
} else {
return '';
}
}

我们看看usercontrol类的onlogin()方法:
uchome_ROOT/uc_client/control/user.php
//note public 外部接口 登陆接口
function onlogin() {
$this->init_input();
$isuid = $this->input('isuid');
$username = $this->input('username');
$password = $this->input('password');
$checkques = $this->input('checkques');
$questionid = $this->input('questionid');
$answer = $this->input('answer');
if($isuid) {
$user = $_ENV['user']->get_user_by_uid($username);
} else {
$user = $_ENV['user']->get_user_by_username($username);
}
//这部分即可改动
$passwordmd5 = preg_match('/^w{32}$/', $password) ? $password : md5($password);
//note 用户名不存在
if(empty($user)) {
$status = -1;
} elseif($user['password'] != md5($passwordmd5.$user['salt'])) {
$status = -2;
} elseif($checkques && $user['secques'] != '' && $user['secques'] != $_ENV['user']->quescrypt($questionid, $answer)) {
$status = -3;
} else {
$status = $user['uid'];
}
$merge = $status != -1 && !$isuid && $_ENV['user']->check_mergeuser($username) ? 1 : 0;
return array($status, $user['username'], $password, $user['email'], $merge);
}

可以改成如下形式:
//note public 外部接口 登陆接
function onlogin($type='myself') {
$this->init_input();
$isuid = $this->input('isuid');
$username = $this->input('username');
$password = $this->input('password');
$checkques = $this->input('checkques');
$questionid = $this->input('questionid');
$answer = $this->input('answer');
if($isuid) {
$user = $_ENV['user']->get_user_by_uid($username);
} else {
$user = $_ENV['user']->get_user_by_username($username);
}

$passwordmd5 = preg_match('/^w{32}$/', $password) ? $password : md5($password);

$type='myself';
if($type=='myself')
{
echo '$password:'.$password.'
';
$testmd5 = md5('test');//假设数据库中保持的所有的密码为test
// print_r($passwordmd5);
// print_r($user);
//note 用户名不存在

if(emptyempty($user)) {
$status = -1;
} elseif($user['password'] != $passwordmd5) {
$status = -2;
} elseif($checkques && $user['secques'] != '' && $user['secques'] != $_ENV['user']->quescrypt($questionid, $answer)) {
$status = -3;
} else {
$status = $user['uid'];
}
// echo '
$statusz:'.$status.'
';
// die();
}else{
if(emptyempty($user)) {
$status = -1;
} elseif($user['password'] != md5($passwordmd5.$user['salt'])) {
$status = -2;
} elseif($checkques && $user['secques'] != '' && $user['secques'] != $_ENV['user']->quescrypt($questionid, $answer)) {
$status = -3;
} else {
$status = $user['uid'];
}
}
$merge = $status != -1 && !$isuid && $_ENV['user']->check_mergeuser($username) ? 1 : 0;
return array($status, $user['username'], $password, $user['email'], $merge);
}

至此,我们可以更改uchome默认的认证方式了,如果这里更改了,以后相关的也需要作出更改,这个就留下大家自己去跟踪调试了.
tips:
uchome_ROOT/uc_client/model/user.php下还有一个check_login(),这个函数暂时没有找到调用的地方.
function check_login($username, $password, &$user) {
$user = $this->get_user_by_username($username);
if(empty($user['username'])) {
return -1;
} elseif($user['password'] != md5(md5($password).$user['salt'])) {
return -2;
}
return $user['uid'];
}

eclipsePDT还是不错的,可以试试这个IDE.
| 0个评论