1,用戶登陸bbs,經過logging.php文件中,使用函數uc _user_login驗證,若是驗證成功,將調用函數 _user_synlogin(位於 uc_client下的client.php文件 中),在這個函數中調用uc _api_post('user', 'synlogin', array('uid'=>$uid));以後向 _API.'/index.php'傳遞了數據;這裏的uc _API就是在 config.inc.php中的定義的 uc_server之URL地址 javascript
2, _server的index.php接受參數數據,得到model爲user,action爲synlogin,就調用control目錄下的user.php類中的onsynlogin方法,經過foreach循環,以javascript的方式通知 應用列表中的應用同步登陸;即經過get方式傳遞給應用目錄中api下的uc .php一些數據; php
3,uc .php接收通知並處理get過來的數據,並在函數synlogin(位於 uc.php中)經過函數uc_authcode加密數據(默認以 _KEY做爲密鑰),用函數uc_setcookie設置cookie; java
4,各個應用在適當的文件中用對應的密鑰解碼上面設置的cookie,獲得用戶id等數據;經過這個值來判斷用戶是否通過其它應用登陸過; web
以discuz舉例: 算法
1、用戶登陸檢查與用戶登陸驗證logging.php api
在bbs的logging.php中以下代碼段 數組
} elseif($action == 'login') { 瀏覽器
if($discuz_uid) { cookie
$ synlogin = ''; app
showmessage('login_s ceed', $indexname);
}
檢查用戶id變量$discuz_uid是否爲空來判斷,用戶是否登陸(包括從別的應用登陸。)
若是用戶從bbs登陸,則在登陸驗證成功後經過以下代碼:
$ synlogin = $allowsynlogin ? uc_user_synlogin($discuz_uid) : '';
通知其它應用----「用戶已從bbs登陸,請通知其它應用設置cookie」
( _server經過javascript調用方式向其它應用的api/ uc.php傳遞數據)
能夠在 應用目錄下新建一個名爲test.php的文件,來模擬登陸成功,請求uc _server通知其它應用。文件內容爲:
---------------------文件內容開始----------------------
<?php
include_once "config.inc.php";
include_once "./ _client/client.php";
echo uc _user_synlogin(1);
echo "<pre>";
var_dump($_COOKIE);
echo "</pre>";
?>
<script type="text/javascript">
var obj=document.getElementsByTagName("script");
for(var i=0;i<obj.length-1;i++) {
document.write("<a href=\""+obj[i].src+"\">"+obj[i].src+"</a><hr>");
}
</script>
---------------------文件內容結束----------------------
ps:這段測試代碼還能夠測試同步登陸很差使的狀況,具體使用方法,你能夠思考一下(本文後面也有介紹),有問題能夠在此文結尾發表評論與我討論。
運行後,查看源代碼便可看到javascript;
這裏要注意了:這些javascript的通知中是不包含用戶登陸的應用的。也就 是說只"通知"用戶未登陸的應用,由於用戶經過 _server登陸成功的當前應用,固然不須要 _server再通知了。具體代碼請參 看:webroot\ _server\control\user.php中的onsynlogin函數的這句:
if($app['synlogin'] && $app['appid'] != $this->app['appid'])
代碼解釋:
$app['synlogin']是 應用是否容許同步登陸
並且應用id不等於用戶當前登陸的應用id
$app數組就是uc _server\data\cache\apps.php中的數組$_CACHE['apps'];
$this->app就是用戶登陸的應用
2、接受其它應用的同步登陸通知:
在discuz的api目錄下的 uc.php中的函數synlogin,在這裏接受 uc_server發送過來的「同步登陸通知」,並設置discuz的cookie,在這個函數中你能夠查看到cookie的加密密鑰的「算法」;
若是你想看看uc _server發送過的的「通知」是什麼數據,你能夠這麼作:
1,修改要接受通知的應用目錄下的api\uc .php,在$action = $get['action'];代碼下面添加以下代碼:
echo "<pre>";var_dump($get);echo "</pre>";die("<hr>api\ uc.php");
2,將上面創建的test.php文件放置在其它容許同步登陸的應用目錄下,並在瀏覽器中運行,而後點擊頁面中對應第一步的應用連接,便可看到 uc_server「通知」給改應用的數據;
---------------------------分割線-------------------------------
function synlogin($get, $post)
在這個函數中經過uc_authcode函數,以密鑰$discuz_auth_key加密了cookie;
在這裏爲了不cookie名稱衝突,在cookie名稱(通常爲:auth)前加了前綴($cookiepre),這個前綴也就是在config.inc.php中設置的那個cookie前綴值;
請看設置cookie的函數uc_setcookie:
(經過參數$prefix來判斷是否對cookie名稱添加前綴$cookiepre)
function uc_setcookie($var, $val , $life = 0, $prefix = 1) {
global $cookiepre, $cookiedomain, $cookiepath, $timestamp, $_SERVER;
setcookie(($prefix ? $cookiepre : '').$var, $val ,
$life ? $timestamp + $life : 0, $cookiepath,
$cookiedomain, $_SERVER['SERVER_PORT'] == 443 ? 1 : 0);
}
密鑰「算法」:
$discuz_auth_key= md5($_DCACHE['settings']['authkey'].$_SERVER['HTTP_USER_AGENT']);
也就是不一樣用戶加密cookie的密鑰可能不一樣;
3、檢查用戶是否已登陸(不管是那個應用下登陸):
discuz的incl?目錄中common.inc.php中有這樣的代碼:
$discuz_auth_key = md5($_DCACHE['settings']['authkey'].$_SERVER['HTTP_USER_AGENT']);
list($discuz_pw, $discuz_secq s, $discuz_uid) = empty($_DCOOKIE['auth']) ? array('', '', 0) : daddslashes(explode("\t", authcode($_DCOOKIE['auth'], 'DECODE')), 1);
這段代碼就是解碼在 .php中用密鑰($discuz_auth_key)加密的 cookie值,以得到用戶id($discuz_uid)這裏的解密函數位於bbs\incl?\global.func.php中,雖然未給函數 傳遞cookie密鑰,但函數中經過全局變量$GLOBALS['discuz_auth_key'])得到密鑰。