以用户登录为例介绍,其它注销,改密码,消息,头像,好友均类同。
- 从用户xxx在某一应用程序的login.php,输入用户名,密码讲起。先用uc_user_login函数到uc_server验证此用户和密码,如正确,则写入session,写入cookies,并更新应用程序会员表中的登录ip,登录时间。用户感觉不到这个过程。
- 然后通过uc_user_synlogin通知uc_server 用户xxx登录成功,这个过程可能使用ajax,用户感觉不到通知过程。
- uc_server收到这个消息后,马上命令手下,把xxx登录的消息,像令牌环一样,发给所有愿意接收(后台中那个是否开启同步登录)这个消息的其它应用程序。其实就是带参数访问一下各应用程序的uc.php,用户感觉不到这个过程。
- 各应用程序靠api下的uc.php来接收uc_server发来的消息,并对uc_server言听计从,让干什么就干什么。现在,收到让xxx用户在你的程序中登录的命令,马上执行。并写本应用程序的session,并且使用p3p,写入相同域或不同域的cookies. 用户感觉不到这个过程。
- 最后所有和uc整合的程序,xxx均登录成功。用户从www.test.com/bbs登录后, 跳到www.test.com/news同样显示登录。因为bbs 和news系统在后台均已登录。
- 应用程序与uc server的会话结束。
得益于uc设计的精巧过程,整个过程,用户完全感觉不到ucenter的存在。这是整合程序历史上的创新。
以下为Supesite的uc_client和ucenter登录通信过程的一个例子:
1、登录入口index.php?action=login
//系统频道
if($_SGET['action'] != 'index') {
if(empty($channels['menus'][$_SGET['action']]['upnameid']) && $channels['menus'][$_SGET['action']]['upnameid'] != 'news') {
$scriptfile = S_ROOT.'./'.$_SGET['action'].'.php';
} else {
$scriptfile = S_ROOT.'./news.php';
}
//echo $scriptfile;
if(file_exists($scriptfile)) {
include_once($scriptfile);
exit();
}
}
提交登录action:batch.login.php?action=login
2、登录处理地址batch.login.php?action=login
include_once(S_ROOT.'./uc_client/client.php');
// 登录操作及其中涉及到的一些函数:
$password = $_POST['password'];
$username = $_POST['username'];
// 去ucenter进行远程登录验证
$ucresult = uc_user_login($username, $password, $loginfield == 'uid');
如果登录成功,则查本地用户信息。如果有更新本地信息,如果没有插入新的用户数据保持与ucenter进行同步。
然后同步其他子系统登录信息:
$msg = $lang['login_succeed'].uc_user_synlogin($members['uid']);
function uc_user_synlogin($uid) {
$uid = intval($uid);
$return = uc_api_post('user', 'synlogin', array('uid'=>$uid));
return $return;
}
下面是一些程序代码与注释:
1 /**
2 * dfopen 方式取指定的模块和动作的数据
3 *
4 * @param string $module 请求的模块
5 * @param string $action 请求的动作
6 * @param array $arg 参数(会加密的方式传送)
7 * @return string
8 */
9 function uc_api_post($module, $action, $arg = array()) {
10 $s = $sep = '';
11 foreach($arg as $k => $v) {
12 $k = urlencode($k);
13 if(is_array($v)) {
14 $s2 = $sep2 = '';
15 foreach($v as $k2 => $v2) {
16 $k2 = urlencode($k2);
17 $s2 .= "$sep2{$k}[$k2]=".urlencode(uc_stripslashes($v2));
18 $sep2 = '&';
19 }
20 $s .= $sep.$s2;
21 } else {
22 $s .= "$sep$k=".urlencode(uc_stripslashes($v));
23 }
24 $sep = '&';
25 }
26 $postdata = uc_api_requestdata($module, $action, $s);
27
28 return uc_fopen2(UC_API.'/index.php', 500000, $postdata, '', TRUE, UC_IP, 20);
29 }
30
31 /**
32 * 构造发送给用户中心的请求数据
33 *
34 * @param string $module 请求的模块
35 * @param string $action 请求的动作
36 * @param string $arg 参数(会加密的方式传送)
37 * @param string $extra 附加参数(传送时不加密)
38 * @return string
39 */
40 function uc_api_requestdata($module, $action, $arg='', $extra='') {
41 $input = uc_api_input($arg);
42 $post = "m=$module&a=$action&inajax=2&release=".UC_CLIENT_RELEASE."&input=$input&appid=".UC_APPID.$extra;
43 return $post;
44 }
45
46 function uc_api_url($module, $action, $arg='', $extra='') {
47 $url = UC_API.'/index.php?'.uc_api_requestdata($module, $action, $arg, $extra);
48 return $url;
49 }
50
51 function uc_api_input($data) {
52 $s = urlencode(uc_authcode($data.'&agent='.md5($_SERVER['HTTP_USER_AGENT'])."&time=".time(), 'ENCODE', UC_KEY));
53 return $s;
54 }
55
56 /**
57 * 远程打开URL
58 * @param string $url 打开的url, 如 http://www.baidu.com/123.htm
59 * @param int $limit 取返回的数据的长度
60 * @param string $post 要发送的 POST 数据,如uid=1&password=1234
61 * @param string $cookie 要模拟的 COOKIE 数据,如uid=123&auth=a2323sd2323
62 * @param bool $bysocket TRUE/FALSE 是否通过SOCKET打开
63 * @param string $ip IP地址
64 * @param int $timeout 连接超时时间
65 * @param bool $block 是否为阻塞模式
66 * @return 取到的字符串
67 */
68 function uc_fopen2($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE) {
69 $__times__ = isset($_GET['__times__']) ? intval($_GET['__times__']) + 1 : 1;
70 if($__times__ > 2