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

相关文章
相关标签/搜索