Ucenter 會員同步登陸通信原理

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'])得到密鑰。

相關文章
相關標籤/搜索