[源码分析] UCenter应用之间的同步登陆和退出分析

mafeiaizj 发布于 2013/11/29 15:41
阅读 1K+
收藏 1

准备工作:

使用的comsenz产品:
UCenter_1.6.0_SC_UTF8 下载链接
Discuz_7.2_SC_UTF8_101020 下载链接

需要用到的程序:
1、自己做好的应用MessageBoard
2、php代码编辑器Notepad++
3、一个允许设置COOKIE的浏览器
4、UCenter和Discuz,简称UC,DX



运行环境:XAMPP


一、安装
安装UCenter_1.6.0_SC_UTF8和Discuz_7.2_SC_UTF8_101020,


二、配置MessageBoard

将MessageBoard挂接到UCenter下,默认通信文件uc.php,允许同步登陆

三、在MessageBoard里调用uc_user_synlogin
uc_user_synlogin的结构: 

function uc_user_synlogin($uid) {//同步登录
        $uid = intval($uid);
        if(@include UC_ROOT.'./data/cache/apps.php') {
                if(count($_CACHE['apps']) > 1) {
                        $return = uc_api_post('user', 'synlogin', array('uid'=>$uid));
                } else {
                        $return = '';
                }
        }
        return $return;
}





uc_user_synlogin函数在uc_client/client.php文件里定义的,大体流程是:
传入一个用户的uid作为参数,转换成整数型,然后加载uc_client/data/cache/apps.php文件,获取里面的数组格式的数据

<?php $_CACHE['apps'] = array (  1 =>   array (  'appid' => '1',  'type' => 'DISCUZX',  'name' => 'Discuz! Board',  'url' => 'http://localhost/php/Discuz_X2/upload',  'ip' => '127.0.0.1',  'viewprourl' => '',  'apifilename' => 'uc.php',  'charset' => '',  'synlogin' => '1',  'extra' => '',  'recvnote' => '1',  ),  2 =>   array (  'appid' => '2',  'type' => 'DISCUZX',  'name' => '测试挂接',  'url' => 'http://localhost/php/Discuz_X2/mycms/',  'ip' => '',  'viewprourl' => '',  'apifilename' => 'uc.php',  'charset' => '',  'synlogin' => '1',  'extra' =>   array (  'apppath' => '',  ),  'recvnote' => '1',  ), ); 





加载完毕之后,就可以使用数组$_CACHE['apps'],这个数组里面保存的是UC下挂接的所有应用的基本信息,先获取这个数组的元素个数,就是UC的应用个数,当数量大于1,就用uc_api_post函数抓去UC的页面输出,这 个函数需要3个参数,第一个user表示使用的模块,我们马上可以联想到uc_server/control/user.php文件的内定义的 usercontrol类,第二个参数synlogin,表示要使用到usercontrol类里面的onsynlogin方法,第三个参数为提交给UC 的参数数组,这里只需要一个uid参数,
然后就是在uc_api_post函数的内部进行加密转换,并使用uc_fopen函数带着必要的参数到UC去抓取uc_server/index.php文件页面输出数据,这些小地方就不细讲了,有兴趣知道内存运算的童鞋可以自己研究代码


 

 

四、UCenter运算分析
当 访问到UC_server/index.php文件时,代码会对传递过来的参数进行过滤和判断,然后加载相应的control模块,这里会加载 uc_server/control/user.php文件,并new一个usercontrol类的实例,这个类继承自base类,然后初始化base 父类,并调用onsynlogin方法

$classname = $m.'control';//$classname = 'usercontrol';    $control = new $classname();  //var_dump($control);exit;  $method = 'on'.$a;//$method = 'onsynlogin';





onsynlogin方法的结构:

function onsynlogin() {  $this->init_input();  $uid = $this->input('uid');  if($this->app['synlogin']) { //当前应用的同步登陆开关  if($this->user = $_ENV['user']->get_user_by_uid($uid)) {//判断uid对应的username是否存在,也就是验证uid是否正确  $synstr = '';//初始化返回变量  foreach($this->cache['apps'] as $appid => $app) {//遍历所有应用,  if($app['synlogin']) {//如果被遍历的应用开启了同步登陆,就执行下面的程序  //拼接访问其他应用的uc.php的url,将地址写在<script>的src属性里  $synstr .= '<script type="text/javascript" src="'.$app['url'].'/api/'.$app['apifilename'].'?time='.$this->time.'&code='.urlencode($this->authcode('action=synlogin&username='.$this->user['username'].'&uid='.$this->user['uid'].'&password='.$this->user['password']."&time=".$this->time, 'ENCODE', $app['authkey'])).'" reload="1"></script>';  //如果有扩展路径,就接上扩展路径  if(is_array($app['extra']['extraurl'])) foreach($app['extra']['extraurl'] as $extraurl) {  $synstr .= '<script type="text/javascript" src="'.$extraurl.'/api/'.$app['apifilename'].'?time='.$this->time.'&code='.urlencode($this->authcode('action=synlogin&username='.$this->user['username'].'&uid='.$this->user['uid'].'&password='.$this->user['password']."&time=".$this->time, 'ENCODE', $app['authkey'])).'" reload="1"></script>';  }  }  }  return $synstr;//返回拼接好的<script>标签代码  }  }  return '';  }





这 个方法的主要作用是先判断请求同步登录的应用是否开启了同步功能,如果开启了,就判断传递过来的uid是否有效,有效的话就遍历UC下所有的应用,判断被 遍历的应用是否开启了同步登录开关(或者叫功能),如果开启了,就拼接这个应用的uc.php文件的访问路径,也就是url地址,然后将需要同步的用户的 uid,username,password和action=synlogin整合加密,作为code键的值,拼接到uc,php的url路径后面,并把 每一个应用的这个url作为一个<script>标签的src属性的值,把所有的<script>标签连接在一起,返回给 MessageBoard应用,

五、MessageBoard输出抓取的数据
由UC返回的数据类似于如下html代码

<script type="text/javascript" src="http://localhost/php/Discuz_X2/upload/api/uc.php?time=1319745201&code=e321fM%2B%2BMjoSRMohx4QN8FWDpzNr7XFTxgIuN43%2F23DC%2BpUEI06EggdSyVtPXkj0GBFDfz3niYdRpH3VzBPsCfd2Q%2BHAfKDkH0JuVBFXZXzE3uielB9XoodJLAPRj6WOF8pWFWlcN0ems3WuPhSmpMI0%2BSDIaEnlptbTgA" reload="1"></script><script type="text/javascript" src="http://localhost/php/Discuz_X2/mycms/api/uc.php?time=1319745201&code=ff7aUh9x92T5DhEa8sWSkV8%2FQD%2BxLNBJkx4Aj2g4ZTdHMRbDyAubAjN6QbP7pbEU3G80FuviLodj6654EiDQSui2tnsg2jKoAhztSH2l7wda84JF5IXuk8gDmXbNYKLFbTRVnmB2mWtrcG2AutLoHKrDqF19CIZNZ0Lkxw" reload="1"></script><script type="text/javascript" src="http://localhost/php/MessageBoard/api/uc.php?time=1319745201&code=11e8GvayEy31N80okXxRIb3y0IW6Qh4BmoJW%2FSNJ7vnMUYya0VJ%2FcyNEhoJu7CEuFyMN5cnai9x6wnqihZ3qaBkVf97teIKIFUFfjEZ3C%2Bf69qpcs7a5BM5skQCSLY6WxebZ4u6e8Y5hpHfiVfP0vek9qeXmaF1C5V0DDQ" reload="1"></script>





可 以看到,每一个应用的uc.php文件的url路径都作为一个<script>标签的外部文件,当我们获取到这段返回数据时,我们要在页面输 出一下这段html代码,因为是js代码,所以,它会加载外部文件,在这里也就是远程其他应用的uc.php文件,到这里我们的浏览器就触发了UC下的所 有开启了同步功能的应用的uc.php文件的代码,并传递过去了time和code参数,

 

 

http://bbs.phpchina.com/thread-225761-1-1.html

加载中
0
Mr_Zhou
Mr_Zhou

帮了大忙了! 

请问添加或者编辑应用之后

uc_client/data/cache/apps.php

这个文件没有更新 

是怎么回事呢。

返回顶部
顶部