浅析phpwind9.0之登陆机制
由于工作的需要,所以开始分析phpwind9.0论坛的部分功能的处理机制,这一节来分析登陆机制。
首先当用户点击进入登陆页面后:(这里不讨论快速登陆和直接在页头登陆的情况,原理基本一致)
进入该类调用run成员函数进入页面初始化。该类继承自PwBaseController这个基础类,这基础类中关于风格会有一些处理。接着回到LoginController类,当用户输入了用户名和密码后,点击提交,调用该类的dorunAction()成员函数,大致流程就是判定验证码以及用户名和密码是否正确,然后形成一个整站的该用户标识,接着进入正常的访问界面,该函数具体如下:
[php] view plaincopy
public function dorunAction() {
$userForm = $this->_getLoginForm();
/* [验证验证码是否正确] */
if ($this->_showVerify()) {
$veryfy = $this->_getVerifyService();
if ($veryfy->checkVerify($userForm['code']) !== true) {
$this->showError('USER:verifycode.error');
}
}
$question = $userForm['question'];
if ($question == -4) {
$question = $this->getInput('myquestion', 'post');
}
/* [验证用户名和密码是否正确] */
$login = new PwLoginService();
$this->runHook('c_login_dorun', $login);
$isSuccess = $login->login($userForm['username'], $userForm['password'], $this->getRequest()->getClientIp(), $question, $userForm['answer']);
if ($isSuccess instanceof PwError) {
$this->showError($isSuccess->getError());
}
$config = Wekit::C('site');
if ($config['windid'] != 'local') {
$localUser = $this->_getUserDs()->getUserByUid($isSuccess['uid'], PwUser::FETCH_MAIN);
if ($localUser['username'] && $userForm['username'] != $localUser['username']) $this->showError('USER:user.syn.error');
}
Wind::import('SRV:user.srv.PwRegisterService');
$registerService = new PwRegisterService();
$info = $registerService->sysUser($isSuccess['uid']);
if (!$info) $this->showError('USER:user.syn.error');
$identity = PwLoginService::createLoginIdentify($info);
$identity = base64_encode($identity . '|' . $this->getInput('backurl') . '|' . $userForm['rememberme']);
/* [是否需要设置安全问题] */
/* @var $userService PwUserService */
$userService = Wekit::load('user.srv.PwUserService');
//解决浏览器记录用户帐号和密码问题
if ($isSuccess['safecv'] && !$question) {
$this->addMessage(true, 'qaE');
$this->showError('USER:verify.question.empty');
}
//该帐号必须设置安全问题
if (empty($isSuccess['safecv']) && $userService->mustSettingSafeQuestion($info['uid'])) {
$this->addMessage(array('url' => WindUrlHelper::createUrl('u/login/setquestion', array('v' => 1, '_statu' => $identity))), 'check');
}
$this->showMessage('', 'u/login/welcome?_statu=' . $identity);
}
第2行代码$userForm = $this->_getLoginForm()是获取表单提交的具体数据,该函数的具体内容在该类中。接着判断验证码和安全问题,然后就是判断用户名和密码是否正确,关键就是其中的这段代码了:
[php] view plaincopy
$login = new PwLoginService();
$this->runHook('c_login_dorun', $login);
$isSuccess = $login->login($userForm['username'], $userForm['password'], $this->getRequest()->getClientIp(), $question, $userForm['answer']);
这里注意 该类的一些成员函数,其中包括login,接下来对登陆模块进行一些hook注册处理,然后进入login实质性的处理部分:
[php] view plaincopy
$isSuccess = $login->login($userForm['username'], $userForm['password'], $this->getRequest()->getClientIp(), $question, $userForm['answer']);
调用PwLoginService类的login成员函数:(用户登陆)
[php] view plaincopy
public function login($username, $password, $ip, $safeQuestion = null, $safeAnswer = '') {
$checkQ = !is_null($safeQuestion) ? true : false;
Wind::import("SRV:user.srv.PwTryPwdBp");
$pwdBp = new PwTryPwdBp();
$info = $pwdBp->auth($username, $password, $ip, $checkQ, $safeQuestion, $safeAnswer);
if ($info instanceof PwError) return $info;
if (($result = $this->runWithVerified('afterLogin', $info)) instanceof PwError) return $result;
return $info;
}
根据phpwind官方手册上的说明
(http://wiki.open.phpwind.com/index.php?title=%E7%B1%BB%E5%BA%93%E5%8A%A0%E8%BD%BD%E6%96%B9%E5%BC%8F)这里的
Wind::import("SRV:user.srv.PwTryPwdBp");即将导入的就是
该类(在该类的第一行代码是导入的有关登陆信息的有效性检查的类),接着我们回到PwLoginService类的login成员函数,看到该行代码:
$info=$pwdBp->auth($username,$password,$ip,$checkQ,$safeQuestion,$safeAnswer);
我们进入PwTryPwdBp类:
[php] view plaincopy
public function auth($username, $password, $ip = '', $checkQ = false, $safeQuestion = '', $safeAnswer = '') {
…
//用户名登录
if ($r[0] == -14 && in_array(3, $this->loginConfig['ways'])) {
$r = $this->_getWindid()->login($username, $password, 2, $checkQ, $safeQuestion, $safeAnswer);
}
return $this->checkVerifyResult($r[0], $r[1]);
}
看到代码:$this->_getWindid(),该成员函数将会通过调用特定的userApi来获取当前用户的信息:
protected function _getWindid() {
return WindidApi::api('user');
}
进入类中经分析,该类
requireWINDID_BOOT.'bootstrap.php'文件,然后调用全局的配置文件:
,得到WINDID_CONNECT的方式为db,接着我们继续查看
类的相关代码:
if (WINDID_CONNECT == 'db') {
$class = Wind::import('WINDID:api.local.'.$class);
$cls[$class] =new$class();
}
而我们通过之前提到的配置文件可知,WINDID对应的就是/src/windid这个目录,于是最终就是调用了
该类,而该类的login成员函数的代码如下:
[php] view plaincopy
public function login($userid, $password, $type = 2, $ifcheck = false, $question = '', $answer = '') {
return $this->_getUserService()->login($userid, $password, $type, $ifcheck, $question, $answer);
}
代码中_getUserService()对应的是该类中的成员函数:
private function _getUserService() {
return Wekit::load('WSRV:user.srv.WindidUserService');
}
WSRV对应的是/src/windid/service目录,这样就是载入
/src/windid/service/user/srv/下的WindidUserService类,然后我们回到之前的代码(即PwTryPwdBp类的auth成员函数的
$r = $this->_getWindid()->login这个代码):我们已经分析完了
$this->_getWindid()这一部分,接着就是调用这一部分返回的结果
(即WindidUserService类)的login函数:
[php] view plaincopy
public function login($userid, $password, $type = 2, $ifcheck = false, $question = '', $answer = '') {
$user = array();
$ds = $this->_getUserDs();
switch ($type){
case 1:
$user = $ds->getUserByUid($userid, WindidUser::FETCH_MAIN);
break;
case 2:
$user = $ds->getUserByName($userid, WindidUser::FETCH_MAIN);
break;
case 3:
$user = $ds->getUserByEmail($userid, WindidUser::FETCH_MAIN);
break;
}
if (!$user) return array(WindidError::USER_NOT_EXISTS);
if ($ifcheck) {
$safecv = WindidUtility::buildQuestion($question, $answer);
if ($safecv != $user['safecv']) return array(WindidError::SAFECV_ERROR, $user);
}
if (WindidUtility::buildPassword($password, $user['salt']) !== $user['password']) {
return array(WindidError::PASSWORD_ERROR, $user);
}
return array(1, $user);
}
显然我们看到这个函数有一个过程,就是先利用用户名访问数据库获取该用户的相关数据($ds = $this->_getUserDs()以及数据库相关的代码将要访问的文件主要是
/src/windid/service/user目录下的文件,比如数据库就是访问dao文件夹),然后利用用户登陆提交的密码经过一定处理后与我们访问数据库获取到的密码进行对比,然后确认用户登陆成功。
针对代码,来说一下这一行:
[php] view plaincopy
if (WindidUtility::buildPassword($password, $user['salt']) !== $user['password']) {
return array(WindidError::PASSWORD_ERROR, $user);
}
这一行主要调用该类下的
buildPassword成员函数,具体内容为:
[php] view plaincopy
public static function buildPassword($password, $salt) {
return md5(md5($password) . $salt);
}
其参数salt是存放在该用户的salt字段中,对应的具体用户表为pw_windid_user表。
分析完最重要的login函数之后,我们回到最初的需要调用该函数的地方:
类中的login成员函数的代码:
[php] view plaincopy
$r = $this->_getWindid()->login($username, $password, 2, $checkQ, $safeQuestion, $safeAnswer);
该login根据上面的的处理可知:返回的是:
[php] view plaincopy
return array(1, $user);
那么将这个数组返回给$r,接着执行:
[php] view plaincopy
return $this->checkVerifyResult($r[0], $r[1]);
该函数还是在该类中,最终返回的是$r[1]这个数组,也就是用户的所有信息,接着我们回到该类的login函数,继续返回该数组,接着返回最初的
,进行登录后的其他处理。
整个登录过程基本就是这样。
本文主要参考了
1.phpwind官方手册:http://wiki.open.phpwind.com/index.php?title=%E9%A6%96%E9%A1%B5
2.Phpwind用户登录机制分析:http://wikimo.net/blogs/330/(这个作用不太大,老版本的,现在新版本流程基本不一样了,不过可以有个了解)
转载请注明出处:http://blog.csdn.net/jayxujia123/article/details/35792649
作者邮箱:xujiaphp@gmail.com
转载于:https://blog.51cto.com/mengphilip/1657745
浅析phpwind9.0之登陆机制相关推荐
- phpwind9.0 read.php 修改,phpwind9.0模板制作教程——制作论坛风格
由于论坛模板机制和门户等模板机制不同,所以今天我就先重点讲讲论坛模板制作的大概过程. 一.先来熟悉下phpwind9.0的论坛模板机制. 其实phpwind9.0的模板机制和discuzx2.5差不多 ...
- .NET1.1中预编译ASP.NET页面实现原理浅析[1]自动预编译机制浅析
.NET1.1中预编译ASP.NET页面实现原理浅析[1]自动预编译机制浅析 .NET1.1中预编译ASP.NET页面实现原理浅析[1]自动预编译机制浅析 作者:&;nbsp来自:网络 htt ...
- Yii 用户登陆机制
Yii 生成应用时已经提供了最基础的用户登陆机制.我们用 Yii 生成一个新的应用,进入 protected/components 目录,我们可以看到 UserIdentity.php 文件,里面的 ...
- 浅析Web2.0技术
浅析Web2.0技术<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&g ...
- ssh免密登陆机制示意图
ssh免密登陆机制示意图
- FreeBSD5.0内核 - 锁机制
FreeBSD5.0内核 - 锁机制 在FreeBSD5.0中,有很多类型的锁:互斥体(struct mtx).共享/独占锁(struct sx).lockmgr锁(struct lock).条件变量 ...
- android8.0 墓碑机制,魔兽世界8.0血DK机制与输出手法详细介绍
魔兽世界8.0血DK机制与输出手法怎么样?很多的童鞋们还不是很清楚,下面小编就来为大家详细的介绍一下血DK的输出机制与技能,感兴趣的玩家快来看看吧! 第一部分 核心体系 核心体系的变化 骨盾的减伤效果 ...
- CloudSim(3.0.3)运行机制见解
CloudSim(3.0.3)运行机制见解 本文为markdown重构版 原文链接:CloudSim(3.0.3)运行机制见解 接到导师的命令,最近几日在学习CloudSim3.0.3的源码,看着看着 ...
- 详解JPA 2.0动态查询机制:Criteria API
转载自详解JPA 2.0动态查询机制:Criteria API-51CTO.若有侵权,请留言删除. 自从 JPA 于 2006 年首次被引入之后,它就得到了 Java 开发社区的广泛支持.该规范的下一 ...
最新文章
- 魔术索引(返回索引值最小的一个)
- (Sql Server)SQL FOR XML PATH
- Spring @Conditional
- 面试必问之JVM原理
- AUTOSAR从入门到精通100讲(三十九)-AUTOSAR 通信服务-Com模块两部曲-概念详解
- C# IIS ManagementException: 访问遭到拒绝
- 【web前端面试题整理03】来看一点CSS相关的吧
- 法兰克机器人外部自动_行业数据 | 服务机器人销售额创新纪录:全球增长32
- [查看内置函数帮助]
- Android BLE开发之Android手机与BLE终端通信
- redis可视化客户端工具TreeNMS
- 什么是黑盒测试?它的常用方法有哪些?
- 蒙特卡洛树搜索(MCTS)
- 华为鸿蒙系统失败,世界首富很无奈,第三大手机系统失败,华为鸿蒙会成功吗...
- Qgis教程07:矢量数据属性编辑
- python的永久存储——pickle‘泡菜’ ,‘腌制’天气查询脚本
- java怎么通过坐标定位控件_[已解决] 可以定位到控件, 但每次执行 click () 方法会报空指针错误 java.lang.NullPointerException...
- 桥牌坐庄训练bm2000 level3闯关记录——A2
- 关键信息基础设施保护条例_五个图表:读懂网络安全等级保护制度与关键信息基础设施保护制度...
- 无限远征服务器,《无限远征队》:玩法丰富的趣味放置RPG,无尽的冒险等你来战...