1、UC通訊原理php
咱們用火狐能夠看到,UCENTER跟應用通訊的地址以下http://bbs.zhiyin.cn/ucenter/admin.php?m=app&a=ping&inajax=1&url=http%3A%2F%2Fapp.zhiyin.cn&ip=192.168.193.64&appid=33&random=1789609938&sid=d6c6MilHehc1GRqHPB14s6eyWNVp84nE3wbbjmf9MBnGQjsqRRnzY%2Fh2w9y1ZXMxvyeT7cSMsJRUaw
html
咱們調試的時候用火狐能夠在「應用管理」菜單中右側右鍵點擊,而後此框架在新標籤頁打開,這樣在火狐firebug中能夠清晰看到get過來的東西,其實也就是html中看到的testlink的地址,只不過加了個隨機碼而已。
ajax
其實請求的是uc服務端的/control/admin/app.php的onping方法(通常狀況下會進入以下紅色的那段的,而不是上面那個IF),代碼以下數據庫
function onping() {
$ip = getgpc('ip');
$url = getgpc('url');
$appid = intval(getgpc('appid'));
$app = $_ENV['app']->get_app_by_appid($appid);
$status = '';
if($app['extra']['apppath'] && @include $app['extra']['apppath'].'./api/'.$app['apifilename']) {
$uc_note = new uc_note();
$status = $uc_note->test($note['getdata'], $note['postdata']);
} else {
$this->load('note');
$url = $_ENV['note']->get_url_code('test', '', $appid);api
//$this->writelog('ping_url', $url);//若是須要看實際的URL爲何,能夠在這裏寫日誌後而後去data/logs裏面去看url,實際上是url/api/uc.php?code=XXXX,code解密後就是action跟time數組,也是後面提到的東西。
$status = $_ENV['app']->test_api($url, $ip);
}
if($status == 1) {
echo 'document.getElementById(\'status_'.$appid.'\').innerHTML = "<img src=\'images/correct.gif\' border=\'0\' class=\'statimg\' \/><span class=\'green\'>'.$this->lang['app_connent_ok'].'</span>";testlink();';
} else {
echo 'document.getElementById(\'status_'.$appid.'\').innerHTML = "<img src=\'images/error.gif\' border=\'0\' class=\'statimg\' \/><span class=\'red\'>'.$this->lang['app_connent_false'].'</span>";testlink();';
}
}數組
請求的是model/app.php的test_api方法瀏覽器
function test_api($url, $ip = '') {
$this->base->load('misc');
if(!$ip) {
$ip = $_ENV['misc']->get_host_by_url($url);
}
if($ip < 0) {
return FALSE;
}
return $_ENV['misc']->dfopen($url, 0, '', '', 1, $ip);
}
服務器
請求的是model/misc.php的dfopen方法,這個方法就不貼了,其實就是一個跟遠程端通訊,看返回的是否是字符串1,是1就通訊成功,0就是通訊失敗,通訊的url是什麼呢,app
其實地址是用get_url_code方法獲取的(能夠在前面的ONPING方法裏面看到是經過$_ENV['note']->get_url_code('test', '', $appid);獲取的),在model/note裏面框架
function get_url_code($operation, $getdata, $appid) {
$app = $this->apps[$appid];
$authkey = $app['authkey'];
$url = $app['url'];
$apifilename = isset($app['apifilename']) && $app['apifilename'] ? $app['apifilename'] : 'uc.php';
$action = $this->operations[$operation][1];
$code = urlencode($this->base->authcode("$action&".($getdata ? "$getdata&" : '')."time=".$this->base->time, 'ENCODE', $authkey));
return $url."/api/$apifilename?code=$code";
}
能夠看出來是與在應用中填寫的地址的api目錄的appfilename通訊,不修改的話將是uc.php
其實如上只是敘述邏輯,真正的UC通訊失敗大可能是由於數據庫連接沒寫正確,服務器時間沒有設置對,客戶端沒有權限連接服務端數據庫,而均可以經過以下幾個方式來排查錯誤。
因此
一、UCENTER是否支持內網通訊(能夠在model/misc.php中的dfopen方法中//$this->writelog('fp', $fp);中看結果,返回資源id則表示自己跟客戶端通訊成功,是客戶端返回錯誤)
絕對支持的,咱們日常的通訊失敗通常都是客戶端這塊寫錯了,所以咱們能夠在客戶端的api目錄裏面寫一個uc2.php,內容爲<?php echo 1;?>,同時在uc應用中將接口文件名換成uc2.php,若是能通訊成功則表示UC服務端跟客戶端通訊沒問題,是你的uc.php寫錯了,問題排查要在這裏排查。若是不能通訊,則是UC服務端沒法經過fsockopen訪問客戶端,多是域名解析問題,也多是你填寫的IP問題,有IP的話服務端會優先用IP跟客戶端通訊的。
二、UCENTER中填不填IP以及IP的做用
其實填寫IP後的通訊速度要比填域名快,這個應用地址其實只是起個域名解析的做用的,最終依然會與客戶端的這個應用的IP進行通訊,也就是api裏面的uc.php通訊。若是你的應用沒上線以前是能夠填寫個局域網的IP用於測試的,不過要保證UC的服務端能跟客戶端的這個IPfsckopen,不然也是會失敗的,檢測方法見第一條。
三、UCENTER通訊是否須要客戶端的數據庫填寫正確以及UC的參數填寫正確(其實UC應用管理裏面生成的數據庫連接參數並不必定在客戶端有權限連接UC的數據庫服務器,這也是致使UC通訊失敗的主要緣由。具體排查方式以下。)
uc.php通常會經過數據庫鏈接的方式跟uc的數據庫表通訊,UC在跟客戶端通訊的時候會發送一個code參數給客戶端,
$code = @$_GET['code'];
parse_str(_authcode($code, 'DECODE', UC_KEY), $get);
if(MAGIC_QUOTES_GPC) {
$get = _stripslashes($get);
}
這個code包含了兩部分的參數,一部分是time,一部分是action,都會放到$get數組裏面,所以咱們在調試uc.php的時候,須要本身寫相似以下代碼模擬從uc發過來的數據
$timestamp = time();
$get['time']=time();//新增行
$get['action']='test';//新增行
if($timestamp - $get['time'] > 3600) {
exit('Authracation has expiried');
}
這樣瀏覽器直接訪問http://app.zhiyin.cn/api/uc.php就能夠準確反映ucenter跟uc.php的通訊結果
四、終極殺招,服務器時間沒有設置對致使通訊失敗,TMD搞了我一上午。
我一步步調試最終到了model/misc.php的dfopen方法中,我在最後一行@fclose($fp);中加入一行$this->writelog('return', $return);由於misc.php中沒有writelog方法,這個方法直接從model/admin.php中提取便可,而後將客戶端的uc.php中加入一行
$timestamp = time();
/*$get['time']=time();
$get['action']='test';
*/
exit($get['time'].'|'.$timestamp.$get['action']);
if($timestamp - $get['time'] > 3600) {
exit('Authracation has expiried');
}
實際上是由於我看/bbs/ucenter/data/logs/中寫的日誌中有Authracation has expiried我纔想到多是UC的服務器跟客戶端的服務器不是一臺服務器,兩臺服務器環境不一樣,取到的時間不一樣致使超時形成「假冒」的通訊失敗,這個通訊失敗是人爲的訪問客戶端http://app.zhiyin.cn/api/uc.php發現不了的,由於你確定是給time以及action賦值了來看是不是客戶端uc.php書寫錯誤致使通訊失敗。但UC服務端實際發送過程當中的時間跟客戶端取到的時間不一致直接報超時。這個通訊失敗我告訴你,通常人是絕對發現不了這個問題的。