Yii框架應用程序整合Ucenter實現同步註冊、登陸和退出等

    現在不少網站都要整合論壇程序,而康盛的Discuz系列產品每每是首選。而後就有了整合用戶的須要,康盛提供了Ucenter架構,方便對不一樣的應用程序進行單點登陸整合。 javascript

 

    進來我嘗試將ucenter整合到Yii網站中,得到了成功,雖然登陸同步程序不是很穩當,基本使用沒有問題了。我將繼續改進。下面說說步驟: php

 

  1. 下載安裝ucenter和discuz,我使用的是ucenter1.6和discuz7.2,因爲7.2自帶的uc_client是舊版本,因此須要覆蓋一下1.6版本。
  2. 複製一份uc_client文件夾到 protected/vendors/下,而後創建一個ucenter.php文件,內容以下:
    Php代碼   收藏代碼
    1. <?php  
    2. include dirname(__FILE__).'/../config/main.php';  
    3. include dirname(__FILE__).'/uc_client/client.php';  
     能夠看到這裏只是包含了兩個文件。而後打開yii的主配置文件 protected/config/main.php,加入ucenter的一些全局變量的設置:
    Php代碼   收藏代碼
    1. <?php  
    2. define('UC_CONNECT''mysql');              // 鏈接 UCenter 的方式: mysql/NULL, 默認爲空時爲 fscoketopen()  
    3.                                             // mysql 是直接鏈接的數據庫, 爲了效率, 建議採用 mysql  
    4. //數據庫相關 (mysql 鏈接時, 而且沒有設置 UC_DBLINK 時, 須要配置如下變量)  
    5. define('UC_DBHOST''localhost');           // UCenter 數據庫主機  
    6. define('UC_DBUSER''root');                // UCenter 數據庫用戶名  
    7. define('UC_DBPW''');                  // UCenter 數據庫密碼  
    8. define('UC_DBNAME''027xfbbs');                // UCenter 數據庫名稱  
    9. define('UC_DBCHARSET''utf8');             // UCenter 數據庫字符集  
    10. define('UC_DBTABLEPRE''027xfbbs.uc_');            // UCenter 數據庫表前綴  
    11.   
    12. //通訊相關  
    13. define('UC_KEY''ebR4GhhpZB7e9Mhb');               // 與 UCenter 的通訊密鑰, 要與 UCenter 保持一致  
    14. define('UC_API''http://027xf.test/ucenter');  // UCenter 的 URL 地址, 在調用頭像時依賴此常量  
    15. define('UC_CHARSET''utf8');               // UCenter 的字符集  
    16. define('UC_IP''');                    // UCenter 的 IP, 當 UC_CONNECT 爲非 mysql 方式時, 而且當前應用服務器解析域名有問題時, 請設置此值  
    17. define('UC_APPID', 2);                  // 當前應用的 ID  
    18.   
    19. // uncomment the following to define a path alias  
    20. // Yii::setPathOfAlias('local','path/to/local-folder');  
    21.   
    22. // This is the main Web application configuration. Any writable  
    23. // CWebApplication properties can be configured here.  
    24. return array(  
    25.     'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..',  
    26.   
    27. .....  
     請根據你的狀況修改上面的數據庫名等設置。
  3. 實現同步註冊,我採用的是定義了表單RegisterForm來處理用戶的註冊,下面是一個典型的註冊表單及其驗證和業務邏輯代碼:
    Php代碼   收藏代碼
    1. <?php  
    2.   
    3. /** 
    4.  * LoginForm class. 
    5.  * LoginForm is the data structure for keeping 
    6.  * user login form data. It is used by the 'login' action of 'SiteController'. 
    7.  */  
    8. class RegisterForm extends CFormModel  
    9. {  
    10.     public $username;  
    11.     public $password;  
    12.     public $repassword;  
    13.     public $email;  
    14.     public $verifyCode;  
    15.   
    16.     /** 
    17.      * Declares the validation rules. 
    18.      * The rules state that username and password are required, 
    19.      * and password needs to be authenticated. 
    20.      */  
    21.     public function rules()  
    22.     {  
    23.         return array(  
    24.             // username and password are required  
    25.             array('username, password, repassword, email, verifyCode''required'),  
    26.             array('username''length''max'=>20, 'min'=>5),  
    27.             // 用戶名惟一性驗證  
    28.             //array('username', 'unique','caseSensitive'=>false,'className'=>'user','message'=>'用戶名"{value}"已經被註冊,請更換'),  
    29.             array('username''checkname'),  
    30.             // 密碼一致性驗證  
    31.             array('repassword''compare''compareAttribute'=>'password','message'=>'兩處輸入的密碼並不一致'),  
    32.             // 電子郵件驗證  
    33.             array('email''email'),  
    34.             // 電子郵件惟一性  
    35.             //array('email', 'unique','caseSensitive'=>false,'className'=>'user','message'=>'電子郵件"{value}"已經被註冊,請更換'),  
    36.             array('email''checkemail'),  
    37.             //array('birthday', 'match', 'pattern'=& gt;'%^\d{4}(\-|\/|\.)\d{1,2}\1\d{1,2}$%', 'allowEmpty'=> true, 'message'=>'生日必須是年-月-日格式'),  
    38.             //array('mobile', 'length', 'max'=>11, 'min'=>11, 'tooLong'=>'手機號碼錯誤','tooShort'=>'手機號碼錯誤'),  
    39.             array('verifyCode''captcha''allowEmpty'=> false),  
    40.         );  
    41.     }  
    42.   
    43.     public function checkname($attribute,$params)  
    44.     {  
    45.         //ucenter  
    46.         Yii::import('application.vendors.*');  
    47.         include_once 'ucenter.php';  
    48.         $flag = uc_user_checkname($this->username);  
    49.           
    50.         switch($flag)  
    51.         {  
    52.             case -1:  
    53.                 $this->addError('username''用戶名不合法');  
    54.                 break;  
    55.             case -2:  
    56.                 $this->addError('username','包含不容許註冊的詞語');  
    57.                 break;  
    58.             case -3:  
    59.                 $this->addError('username','用戶名已經存在');  
    60.                 break;  
    61.         }  
    62.     }  
    63.       
    64.     public function checkemail($attribute,$params)  
    65.     {  
    66.         //ucenter  
    67.         Yii::import('application.vendors.*');  
    68.         include_once 'ucenter.php';  
    69.         $flag = uc_user_checkemail($this->email);  
    70.   
    71.         switch($flag)  
    72.         {  
    73.             case -4:  
    74.                 $this->addError('email''Email 格式有誤');  
    75.                 break;  
    76.             case -5:  
    77.                 $this->addError('email','Email 不容許註冊');  
    78.                 break;  
    79.             case -6:  
    80.                 $this->addError('email','該 Email 已經被註冊');  
    81.                 break;  
    82.         }  
    83.     }  
    84.   
    85.     /** 
    86.      * Declares attribute labels. 
    87.      */  
    88.     public function attributeLabels()  
    89.     {  
    90.         return array(  
    91.             'username'=>'設定用戶名',  
    92.             'password'=>'設定密碼',  
    93.             'repassword'=>'再次輸入密碼',  
    94.             'email'=>'電子郵件地址',  
    95.             'mobile'=>'手機號碼',  
    96.             'verifyCode'=>'驗證碼',  
    97.         );  
    98.     }  
    99.   
    100.     /** 
    101.      * 註冊用戶 
    102.      * @return boolean whether register is successful 
    103.      */  
    104.     public function register($uid)  
    105.     {  
    106.         //ucenter  
    107.         Yii::import('application.vendors.*');  
    108.         include_once 'ucenter.php';  
    109.         $uid = uc_user_register($this->username, $this->password, $this->email);  
    110.         if($uid>0)  
    111.         {  
    112.             $model = new user;  
    113.             $model->attributes = $_POST['RegisterForm'];  
    114.             $model->password = md5($_POST['RegisterForm']['password']);  
    115.             $model->id = $uid;  
    116.               
    117.             return $model->save();  
    118.         }  
    119.     }  
    120. }  
     咱們看看上面的代碼,調用了uc_user_checkname和uc_user_checkemail完成了用戶名和email的驗證,而後調用了 uc_user_register將用戶註冊到ucenter,成功後,再註冊到Yii應用。
  4. 實現用戶登陸,典型的Yii應用使用 CUserIdentity來實現登陸,咱們要作的就是繼承它,實現本身的驗證邏輯:
    Php代碼   收藏代碼
    1. <?php  
    2.   
    3. /** 
    4.  * UserIdentity represents the data needed to identity a user. 
    5.  * It contains the authentication method that checks if the provided 
    6.  * data can identity the user. 
    7.  */  
    8. class UserIdentity extends CUserIdentity  
    9. {     
    10.     public $id;  
    11.     /** 
    12.      * Authenticates a user. 
    13.      * The example implementation makes sure if the username and password 
    14.      * are both 'demo'. 
    15.      * In practical applications, this should be changed to authenticate 
    16.      * against some persistent user identity storage (e.g. database). 
    17.      * @return boolean whether authentication succeeds. 
    18.      */  
    19.     public function authenticate()  
    20.     {  
    21.         //ucenter  
    22.         Yii::import('application.vendors.*');  
    23.         include_once 'ucenter.php';  
    24.         list($uid$username$password$email) = uc_user_login($this->username, $this->password);  
    25.         if($uid > 0)  
    26.         {  
    27.             $user = user::model()->findByPk($uid);  
    28.               
    29.             if($user == null)//說明網站數據庫中沒有,而ucenter中有這個用戶,添加用戶  
    30.             {  
    31.                 $user = new user;  
    32.                 $user->username = $username;  
    33.                 $user->password = md5($password);  
    34.                 $user->email = $email;  
    35.                 $user->id = $uid;  
    36.                 $user->save();  
    37.                   
    38.                 $user->refresh();  
    39.             }  
    40.               
    41.             $this->username = $user->username;  
    42.             $this->id = $user->id;  
    43.               
    44.             $user->last_login_time = $user->this_login_time;  
    45.             $user->this_login_time = time();  
    46.             $user->last_login_ip = $user->this_login_ip;  
    47.             $user->this_login_ip = Yii::app()->getRequest()->userHostAddress;  
    48.             $user->save();   
    49.               
    50.             $this->errorCode=self::ERROR_NONE;  
    51.         }  
    52.         elseif($uid == -1)  
    53.         {  
    54.             $this->errorCode=self::ERROR_USERNAME_INVALID;  
    55.         }  
    56.         elseif($uid == -2)  
    57.         {  
    58.             $this->errorCode=self::ERROR_PASSWORD_INVALID;  
    59.         }  
    60.           
    61.         return !$this->errorCode;  
    62.     }  
    63.       
    64.     public function getId()  
    65.     {  
    66.         return $this->id;  
    67.     }  
    68. }  
     請根據本身的應用狀況進行修改便可,這裏咱們不須要對Yii的用戶登陸作任何修改。
  5. 而後咱們修改 SiteController/actionLogin 方法,將同步登陸其餘應用的js輸出到瀏覽器:
    Php代碼   收藏代碼
    1. /** 
    2.      * Displays the login page 
    3.      */  
    4.     public function actionLogin()  
    5.     {  
    6.         $model=new LoginForm;  
    7.   
    8.         // if it is ajax validation request  
    9.         if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')  
    10.         {  
    11.             echo CActiveForm::validate($model);  
    12.             Yii::app()->end();  
    13.         }  
    14.   
    15.         // collect user input data  
    16.         if(isset($_POST['LoginForm']))  
    17.         {  
    18.             $model->attributes=$_POST['LoginForm'];  
    19.             // validate user input and redirect to the previous page if valid  
    20.             if($model->validate() && $model->login())  
    21.             {  
    22.                 //ucenter  
    23.                 Yii::import('application.vendors.*');  
    24.                 include_once 'ucenter.php';  
    25.                 $script = uc_user_synlogin(Yii::app()->user->id);  
    26.                 $this->render('loginsuc'array(  
    27.                     'script' => $script,  
    28.                 ));  
    29.                 Yii::app()->end();  
    30.             }  
    31.         }  
    32.         // display the login form  
    33.         $this->render('login',array('model'=>$model));  
    34.     }  
     簡單的loginsuc.php視圖文件:
    Php代碼   收藏代碼
    1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
    2. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">  
    3. <head>  
    4.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
    5. </head>  
    6. <body>  
    7. <?php   
    8. $this->layout = 'none';  
    9. echo $script;   
    10. ?>  
    11. <script type="text/javascript">setTimeout('location.href="<?php echo Yii::app()->user->returnUrl ?>"',3000);</script>  
    12. 登陸成功,正在返回登陸前頁面...  
    13. </body>  
    14. </html>  
     
  6. 繼續修改 SiteController/actionLogout方法,實現同步退出:
    Php代碼   收藏代碼
    1. /** 
    2.      * Logs out the current user and redirect to homepage. 
    3.      */  
    4.     public function actionLogout()  
    5.     {  
    6.         Yii::app()->user->logout();  
    7.         //ucenter  
    8.         Yii::import('application.vendors.*');  
    9.         include_once 'ucenter.php';  
    10.         $script = uc_user_synlogout();  
    11.         $this->render('logoutsuc'array(  
    12.             'script' => $script,  
    13.         ));  
    14.         Yii::app()->end();  
    15.     }  
    16.       
      簡單的logoutsuc.php視圖文件:
    Php代碼   收藏代碼
    1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
    2. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">  
    3. <head>  
    4.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
    5. </head>  
    6. <body>  
    7. <?php   
    8. $this->layout = 'none';  
    9. echo $script;   
    10. ?>  
    11. <script type="text/javascript">setTimeout('location.href="<?php echo Yii::app()->homeUrl ?>"',3000);</script>  
    12. 退出成功,正在返回首頁...  
    13. </body>  
    14. </html>  
     
  7. 進行到這裏,咱們已經實現了整合ucenter的登陸和註冊了,這樣ucenter中有的用戶,能夠登陸到yii應用,yii應用也能夠註冊用戶 到ucenter了。可是這尚未完成,咱們須要的是在discuz中用戶登陸時,也同步登陸yii應用,退出亦然,那麼咱們須要實現 Yii應用的 api/uc.php 這個接口程序。因爲咱們要用到Yii的框架資源,因此我沒有采用硬編碼的方式實現這個接口,而是建立了一個UcApplication類完成這個任務,繼 續往下看。
  8. 首先創建 api/uc.php 入口文件,代碼以下:
    Php代碼   收藏代碼
    1. <?php  
    2. define('UC_CLIENT_VERSION''1.6.0');  
    3. define('UC_CLIENT_RELEASE''20110501');  
    4.   
    5. define('API_DELETEUSER', 1);        //note 用戶刪除 API 接口開關  
    6. define('API_RENAMEUSER', 1);        //note 用戶更名 API 接口開關  
    7. define('API_GETTAG', 1);        //note 獲取標籤 API 接口開關  
    8. define('API_SYNLOGIN', 1);      //note 同步登陸 API 接口開關  
    9. define('API_SYNLOGOUT', 1);     //note 同步登出 API 接口開關  
    10. define('API_UPDATEPW', 1);      //note 更改用戶密碼 開關  
    11. define('API_UPDATEBADWORDS', 1);    //note 更新關鍵字列表 開關  
    12. define('API_UPDATEHOSTS', 1);       //note 更新域名解析緩存 開關  
    13. define('API_UPDATEAPPS', 1);        //note 更新應用列表 開關  
    14. define('API_UPDATECLIENT', 1);      //note 更新客戶端緩存 開關  
    15. define('API_UPDATECREDIT', 1);      //note 更新用戶積分 開關  
    16. define('API_GETCREDITSETTINGS', 1); //note 向 UCenter 提供積分設置 開關  
    17. define('API_GETCREDIT', 1);     //note 獲取用戶的某項積分 開關  
    18. define('API_UPDATECREDITSETTINGS', 1);  //note 更新應用積分設置 開關  
    19.   
    20. define('API_RETURN_SUCCEED''1');  
    21. define('API_RETURN_FAILED''-1');  
    22. define('API_RETURN_FORBIDDEN''-2');  
    23.   
    24. // change the following paths if necessary  
    25. $yii=dirname(__FILE__).'/../protected/yii-1.1.6/framework/yii.php';  
    26. $config=dirname(__FILE__).'/../protected/config/main.php';  
    27.   
    28. // remove the following lines when in production mode  
    29. defined('YII_DEBUG'or define('YII_DEBUG',true);  
    30. // specify how many levels of call stack should be shown in each log message  
    31. defined('YII_TRACE_LEVEL'or define('YII_TRACE_LEVEL',0);  
    32.   
    33. require_once($yii);  
    34. require(dirname(__FILE__).'/../protected/components/UcApplication.php');  
    35. Yii::createApplication('UcApplication'$config)->run();  
     這裏能夠看到,這個腳本和標準的index.php是同樣的,只是使用了不一樣的Application類。咱們接着看這個類。
  9. 創建 protected/components/UcApplication.php類文件:
    Php代碼   收藏代碼
    1. <?php  
    2. class UcApplication extends CWebApplication  
    3. {  
    4.     public $defaultController = 'Uc';  
    5.       
    6.     private $route = '';  
    7.       
    8.     protected function preinit()  
    9.     {  
    10.         $this->parseRequest();  
    11.     }  
    12.       
    13.     private function parseRequest()  
    14.     {  
    15.         $_DCACHE = $get = $post = array();  
    16.   
    17.         $code = @$_GET['code'];  
    18.         parse_str($this->_authcode($code'DECODE', UC_KEY), $get);  
    19.         if(MAGIC_QUOTES_GPC) {  
    20.             $get = $this->_stripslashes($get);  
    21.         }  
    22.           
    23.         $timestamp = time();  
    24.         if($timestamp - $get['time'] > 3600) {  
    25.             //exit('Authracation has expiried');  
    26.         }  
    27.         if(emptyempty($get)) {  
    28.             exit('Invalid Request');  
    29.         }  
    30.         $action = $get['action'];  
    31.           
    32.         require_once 'xml.class.php';  
    33.         $post = xml_unserialize(file_get_contents('php://input'));  
    34.         Yii::log($get'debug');  
    35.         Yii::log($post'debug');  
    36.         $_GET = $get;  
    37.         $_POST = $post;  
    38.           
    39.         $this->route = $this->defaultController .'/'$action;  
    40.           
    41.         if(!in_array($actionarray('test''deleteuser''renameuser''gettag''synlogin''synlogout''updatepw''updatebadwords''updatehosts''updateapps''updateclient''updatecredit''getcreditsettings''updatecreditsettings')))   
    42.         {  
    43.             exit(API_RETURN_FAILED);  
    44.         }  
    45.     }  
    46.       
    47.     public function processRequest()  
    48.     {  
    49.         $this->runController($this->route);  
    50.     }  
    51.       
    52.     private function _authcode($string$operation = 'DECODE'$key = ''$expiry = 0) {  
    53.         $ckey_length = 4;  
    54.       
    55.         $key = md5($key ? $key : UC_KEY);  
    56.         $keya = md5(substr($key, 0, 16));  
    57.         $keyb = md5(substr($key, 16, 16));  
    58.         $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';  
    59.       
    60.         $cryptkey = $keya.md5($keya.$keyc);  
    61.         $key_length = strlen($cryptkey);  
    62.       
    63.         $string = $operation == 'DECODE' ? base64_decode(substr($string$ckey_length)) : sprintf('%010d'$expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;  
    64.         $string_length = strlen($string);  
    65.       
    66.         $result = '';  
    67.         $box = range(0, 255);  
    68.       
    69.         $rndkey = array();  
    70.         for($i = 0; $i <= 255; $i++) {  
    71.             $rndkey[$i] = ord($cryptkey[$i % $key_length]);  
    72.         }  
    73.       
    74.         for($j = $i = 0; $i < 256; $i++) {  
    75.             $j = ($j + $box[$i] + $rndkey[$i]) % 256;  
    76.             $tmp = $box[$i];  
    77.             $box[$i] = $box[$j];  
    78.             $box[$j] = $tmp;  
    79.         }  
    80.       
    81.         for($a = $j = $i = 0; $i < $string_length$i++) {  
    82.             $a = ($a + 1) % 256;  
    83.             $j = ($j + $box[$a]) % 256;  
    84.             $tmp = $box[$a];  
    85.             $box[$a] = $box[$j];  
    86.             $box[$j] = $tmp;  
    87.             $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));  
    88.         }  
    89.       
    90.         if($operation == 'DECODE') {  
    91.             if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {  
    92.                 return substr($result, 26);  
    93.             } else {  
    94.                     return '';  
    95.                 }  
    96.         } else {  
    97.             return $keyc.str_replace('='''base64_encode($result));  
    98.         }  
    99.       
    100.     }  
    101.   
    102.     private function _stripslashes($string) {  
    103.         if(is_array($string)) {  
    104.             foreach($string as $key => $val) {  
    105.                 $string[$key] = $this->_stripslashes($val);  
    106.             }  
    107.         } else {  
    108.             $string = stripslashes($string);  
    109.         }  
    110.         return $string;  
    111.     }  
    112. }  
     這裏能夠看到,主要邏輯是processRequest方法,實現了ucenter通知的解碼、調用相應的控制器和動做實現操做。
  10. 而後創建 protected/controller/UcController.php文件,代碼以下:
    Php代碼   收藏代碼
    1. <?php  
    2. class UcController extends Controller  
    3. {  
    4.     private $appdir = '';  
    5.       
    6.     protected function beforeAction(CAction $action)  
    7.     {  
    8.         $this->appdir = Yii::app()->basePath . '/vendors/';  
    9.         return parent::beforeAction($action);  
    10.     }  
    11.       
    12.     public function actionTest() {  
    13.         echo API_RETURN_SUCCEED;  
    14.     }  
    15.   
    16.     public function actionDeleteuser() {  
    17.         $uids = explode(','str_replace("'", '', $_GET['ids']));  
    18.         !API_DELETEUSER && exit(API_RETURN_FORBIDDEN);  
    19.           
    20.         $users = user::model()->findAllByPk($uids);  
    21.         foreach($users as $user)  
    22.         {  
    23.             $user->delete();  
    24.         }  
    25.   
    26.         echo API_RETURN_SUCCEED;  
    27.     }  
    28.   
    29.     public function actionRenameuser() {  
    30.         $uid = $_GET['uid'];  
    31.         $usernameold = $_GET['oldusername'];  
    32.         $usernamenew = $_GET['newusername'];  
    33.         if(!API_RENAMEUSER) {  
    34.             echo API_RETURN_FORBIDDEN;  
    35.         }  
    36.           
    37.         $user = user::model()->findByPk($uid);  
    38.         if($user !== null)  
    39.         {  
    40.             $user->username = $usernamenew;  
    41.             if($user->save(false))  
    42.                 echo API_RETURN_SUCCEED;  
    43.             else  
    44.                 echo API_RETURN_FAILED;  
    45.         }  
    46.     }  
    47.   
    48.     public function actionGettag() {  
    49.         $name = $_GET['id'];  
    50.         if(!API_GETTAG) {  
    51.             echo API_RETURN_FORBIDDEN;  
    52.         }  
    53.           
    54.         $echo = array();  
    55.         echo $this->_serialize($return, 1);  
    56.     }  
    57.   
    58.     public function actionSynlogin() {  
    59.         $uid = $_GET['uid'];  
    60.         $username = $_GET['username'];  
    61.         if(!API_SYNLOGIN) {  
    62.             echo API_RETURN_FORBIDDEN;  
    63.         }  
    64.           
    65.         $identity=new UcUserIdentity($username);  
    66.   
    67.         if($identity->authenticate())  
    68.         {  
    69.             Yii::app()->user->login($identity, 0);  
    70.         }  
    71.   
    72.         header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');  
    73.         //$_SESSION[Yii::app()->user->stateKeyPrefix.'__id'] = $uid;  
    74.         //$_SESSION[Yii::app()->user->stateKeyPrefix.'__name'] = $username;  
    75.     }  
    76.   
    77.     public function actionSynlogout() {  
    78.         if(!API_SYNLOGOUT) {  
    79.             echo API_RETURN_FORBIDDEN;  
    80.         }  
    81.   
    82.         //note 同步登出 API 接口  
    83.         header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');  
    84.         Yii::app()->user->logout();  
    85.     }  
    86.   
    87.     public function actionUpdatepw() {  
    88.         if(!API_UPDATEPW) {  
    89.             echo API_RETURN_FORBIDDEN;  
    90.         }  
    91.         $username = $_GET['username'];  
    92.         $password = $_GET['password'];  
    93.           
    94.         $user = user::model()->findByAttributes(array('username'=>$username));  
    95.         if($user !== null)  
    96.         {  
    97.             $user->password = md5($password);  
    98.             if($user->save())  
    99.                 echo API_RETURN_SUCCEED;  
    100.             else  
    101.                 echo API_RETURN_FAILED;  
    102.         }  
    103.         else  
    104.             echo API_RETURN_FAILED;  
    105.     }  
    106.   
    107.     public function actionUpdatebadwords() {  
    108.         if(!API_UPDATEBADWORDS) {  
    109.             echo API_RETURN_FORBIDDEN;  
    110.         }  
    111.         $cachefile = $this->appdir.'./uc_client/data/cache/badwords.php';  
    112.         $fp = fopen($cachefile'w');  
    113.         $data = array();  
    114.         if(is_array($_POST)) {  
    115.             foreach($_POST as $k => $v) {  
    116.                 $data['findpattern'][$k] = $v['findpattern'];  
    117.                 $data['replace'][$k] = $v['replacement'];  
    118.             }  
    119.         }  
    120.         $s = "<?php\r\n";  
    121.         $s .= '$_CACHE[\'badwords\'] = '.var_export($data, TRUE).";\r\n";  
    122.         fwrite($fp$s);  
    123.         fclose($fp);  
    124.         echo API_RETURN_SUCCEED;  
    125.     }  
    126.   
    127.     public function actionUpdatehosts() {  
    128.         if(!API_UPDATEHOSTS) {  
    129.             echo API_RETURN_FORBIDDEN;  
    130.         }  
    131.         $cachefile = $this->appdir.'./uc_client/data/cache/hosts.php';  
    132.         $fp = fopen($cachefile'w');  
    133.         $s = "<?php\r\n";  
    134.         $s .= '$_CACHE[\'hosts\'] = '.var_export($_POST, TRUE).";\r\n";  
    135.         fwrite($fp$s);  
    136.         fclose($fp);  
    137.         echo API_RETURN_SUCCEED;  
    138.     }  
    139.   
    140.     public function actionUpdateapps() {  
    141.         if(!API_UPDATEAPPS) {  
    142.             echo API_RETURN_FORBIDDEN;  
    143.         }  
    144.         $UC_API = $_POST['UC_API'];  
    145.   
    146.         //note 寫 app 緩存文件  
    147.         $cachefile = $this->appdir.'./uc_client/data/cache/apps.php';  
    148.         $fp = fopen($cachefile'w');  
    149.         $s = "<?php\r\n";  
    150.         $s .= '$_CACHE[\'apps\'] = '.var_export($_POST, TRUE).";\r\n";  
    151.         fwrite($fp$s);  
    152.         fclose($fp);  
    153.   
    154.         //note 寫配置文件  
    155.         $config_file = Yii::app()->basePath.'./config/main.php';  
    156.         if(is_writeable($config_file)) {  
    157.             $configfile = trim(file_get_contents($config_file));  
    158.             $configfile = substr($configfile, -2) == '?>' ? substr($configfile, 0, -2) : $configfile;  
    159.             $configfile = preg_replace("/define\('UC_API',\s*'.*?'\);/i""define('UC_API', '$UC_API');"$configfile);  
    160.             if($fp = @fopen($config_file'w')) {  
    161.                 @fwrite($fp, trim($configfile));  
    162.                 @fclose($fp);  
    163.             }  
    164.         }  
    165.       
    166.         echo API_RETURN_SUCCEED;  
    167.     }  
    168.   
    169.     public function actionUpdateclient() {  
    170.         if(!API_UPDATECLIENT) {  
    171.             echo API_RETURN_FORBIDDEN;  
    172.         }  
    173.         $cachefile = $this->appdir.'./uc_client/data/cache/settings.php';  
    174.         $fp = fopen($cachefile'w');  
    175.         $s = "<?php\r\n";  
    176.         $s .= '$_CACHE[\'settings\'] = '.var_export($_POST, TRUE).";\r\n";  
    177.         fwrite($fp$s);  
    178.         fclose($fp);  
    179.         echo API_RETURN_SUCCEED;  
    180.     }  
    181.   
    182.     public function actionUpdatecredit() {  
    183.         if(!API_UPDATECREDIT) {  
    184.             echo API_RETURN_FORBIDDEN;  
    185.         }  
    186.         $credit = $_GET['credit'];  
    187.         $amount = $_GET['amount'];  
    188.         $uid = $_GET['uid'];  
    189.         echo API_RETURN_SUCCEED;  
    190.     }  
    191.   
    192.     public function actionGetcredit() {  
    193.         if(!API_GETCREDIT) {  
    194.             echo API_RETURN_FORBIDDEN;  
    195.         }  
    196.     }  
    197.   
    198.     public function actionGetcreditsettings() {  
    199.         if(!API_GETCREDITSETTINGS) {  
    200.             echo API_RETURN_FORBIDDEN;  
    201.         }  
    202.         $credits = array();  
    203.         echo $this->_serialize($credits);  
    204.     }  
    205.   
    206.     public function actionUpdatecreditsettings() {  
    207.         if(!API_UPDATECREDITSETTINGS) {  
    208.             echo API_RETURN_FORBIDDEN;  
    209.         }  
    210.         echo API_RETURN_SUCCEED;  
    211.     }  
    212.       
    213.     private function _serialize($arr$htmlon = 0) {  
    214.         if(!function_exists('xml_serialize')) {  
    215.             include_once 'xml.class.php';  
    216.         }  
    217.         echo xml_serialize($arr$htmlon);  
    218.     }  
    219. }  
     
    上面用到了xml.class.php這個類文件,能夠在uc_client/lib目錄找到。
    這裏須要說明的是,actionSynlogin方法中,利用了我定義的特殊的UserIdentity來登陸的,由於不須要提供密碼。
  11. 再來看看最後一個類:
    Php代碼   收藏代碼
    1. <?php  
    2.   
    3. /** 
    4.  * UserIdentity represents the data needed to identity a user. 
    5.  * It contains the authentication method that checks if the provided 
    6.  * data can identity the user. 
    7.  */  
    8. class UcUserIdentity extends CUserIdentity  
    9. {     
    10.     public $id;  
    11.       
    12.     /** 
    13.      * Constructor. 
    14.      * @param string $username username 
    15.      */  
    16.     public function __construct($username)  
    17.     {  
    18.         $this->username=$username;  
    19.         $this->password='';  
    20.     }  
    21.     /** 
    22.      * Authenticates a user. 
    23.      * The example implementation makes sure if the username and password 
    24.      * are both 'demo'. 
    25.      * In practical applications, this should be changed to authenticate 
    26.      * against some persistent user identity storage (e.g. database). 
    27.      * @return boolean whether authentication succeeds. 
    28.      */  
    29.     public function authenticate()  
    30.     {  
    31.         $user = user::model()->findByAttributes(array('username'=>$this->username));  
    32.           
    33.         if($user == null)//說明網站數據庫中沒有,而ucenter中有這個用戶,添加用戶  
    34.         {  
    35.             //ucenter  
    36.             Yii::import('application.vendors.*');  
    37.             include_once 'ucenter.php';  
    38.             list($uid$username$email) = uc_get_user($this->username);  
    39.             if($uid)  
    40.             {  
    41.                 $user = new user;  
    42.                 $user->username = $username;  
    43.                 $user->password = md5(rand(10000,99999));  
    44.                 $user->email = $email;  
    45.                 $user->id = $uid;  
    46.                 $user->save();  
    47.                   
    48.                 $user->refresh();  
    49.             }  
    50.         }  
    51.           
    52.         $this->id = $user->id;  
    53.           
    54.         $user->last_login_time = $user->this_login_time;  
    55.         $user->this_login_time = time();  
    56.         $user->last_login_ip = $user->this_login_ip;  
    57.         $user->this_login_ip = Yii::app()->getRequest()->userHostAddress;  
    58.         $user->save();   
    59.           
    60.         $this->errorCode=self::ERROR_NONE;  
    61.           
    62.         return !$this->errorCode;  
    63.     }  
    64.       
    65.     public function getId()  
    66.     {  
    67.         return $this->id;  
    68.     }  
    69. }  
     能夠看到,在這個認證類中,實現了對yii應用中沒有的用戶的創建操做。而後不須要對yii應用作任何特殊設置,就能夠實現api接口了。
  12. 而後咱們在ucenter中添加yii應用的設置,修改main.php中的相應設置,應該就能夠實現ucenter的同步登陸、註冊、退出、刪除用戶、修改用戶名等等功能了!這個實現方法相對很Yii,呵呵。

有什麼問題,歡迎評論,和我聯繫。你們一塊兒進步吧! html

 

PS: 須要注意的是,整合了ucenter的Yii應用在部署時,需將 protected/vendors/uc_client/data/及其子目錄、文件設爲可寫。不然將會有些奇怪的問題。 java

相關文章
相關標籤/搜索