浅析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之登陆机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转]脏读,不可重复读,幻读的理解
- 下一篇: 使用dom4j解析XML文件