uc_client是如何与UCenter进行通信的

整合程序历史上的创新
服务器君一共花费了300.972 ms进行了4次数据库查询,努力地为您提供了这个页面。
试试阅读模式?希望听取您的建议

以用户登录为例介绍,其它注销,改密码,消息,头像,好友均类同。

  1. 从用户xxx在某一应用程序的login.php,输入用户名,密码讲起。先用uc_user_login函数到uc_server验证此用户和密码,如正确,则写入session,写入cookies,并更新应用程序会员表中的登录ip,登录时间。用户感觉不到这个过程。
  2. 然后通过uc_user_synlogin通知uc_server 用户xxx登录成功,这个过程可能使用ajax,用户感觉不到通知过程。
  3. uc_server收到这个消息后,马上命令手下,把xxx登录的消息,像令牌环一样,发给所有愿意接收(后台中那个是否开启同步登录)这个消息的其它应用程序。其实就是带参数访问一下各应用程序的uc.php,用户感觉不到这个过程。
  4. 各应用程序靠api下的uc.php来接收uc_server发来的消息,并对uc_server言听计从,让干什么就干什么。现在,收到让xxx用户在你的程序中登录的命令,马上执行。并写本应用程序的session,并且使用p3p,写入相同域或不同域的cookies.   用户感觉不到这个过程。
  5. 最后所有和uc整合的程序,xxx均登录成功。用户从www.test.com/bbs登录后, 跳到www.test.com/news同样显示登录。因为bbs 和news系统在后台均已登录。
  6. 应用程序与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;
}

下面是一些程序代码与注释:

/**
 *  dfopen 方式取指定的模块和动作的数据
 *
 * @param string $module	请求的模块
 * @param string $action 	请求的动作
 * @param array $arg		参数(会加密的方式传送)
 * @return string
 */
function uc_api_post($module, $action, $arg = array()) {
	$s = $sep = '';
	foreach($arg as $k => $v) {
		$k = urlencode($k);
		if(is_array($v)) {
			$s2 = $sep2 = '';
			foreach($v as $k2 => $v2) {
				$k2 = urlencode($k2);
				$s2 .= "$sep2{$k}[$k2]=".urlencode(uc_stripslashes($v2));
				$sep2 = '&';
			}
			$s .= $sep.$s2;
		} else {
			$s .= "$sep$k=".urlencode(uc_stripslashes($v));
		}
		$sep = '&';
	}
	$postdata = uc_api_requestdata($module, $action, $s);
	
	return uc_fopen2(UC_API.'/index.php', 500000, $postdata, '', TRUE, UC_IP, 20);
}

/**
 * 构造发送给用户中心的请求数据
 *
 * @param string $module	请求的模块
 * @param string $action	请求的动作
 * @param string $arg		参数(会加密的方式传送)
 * @param string $extra		附加参数(传送时不加密)
 * @return string
 */
function uc_api_requestdata($module, $action, $arg='', $extra='') {
	$input = uc_api_input($arg);
	$post = "m=$module&a=$action&inajax=2&release=".UC_CLIENT_RELEASE."&input=$input&appid=".UC_APPID.$extra;
	return $post;
}

function uc_api_url($module, $action, $arg='', $extra='') {
	$url = UC_API.'/index.php?'.uc_api_requestdata($module, $action, $arg, $extra);
	return $url;
}

function uc_api_input($data) {
	$s = urlencode(uc_authcode($data.'&agent='.md5($_SERVER['HTTP_USER_AGENT'])."&time=".time(), 'ENCODE', UC_KEY));
	return $s;
}

/**
 *  远程打开URL
 *  @param string $url		打开的url, 如 http://www.baidu.com/123.htm
 *  @param int $limit		取返回的数据的长度
 *  @param string $post		要发送的 POST 数据,如uid=1&password=1234
 *  @param string $cookie	要模拟的 COOKIE 数据,如uid=123&auth=a2323sd2323
 *  @param bool $bysocket	TRUE/FALSE 是否通过SOCKET打开
 *  @param string $ip		IP地址
 *  @param int $timeout		连接超时时间
 *  @param bool $block		是否为阻塞模式
 *  @return			取到的字符串
 */
function uc_fopen2($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE) {
	$__times__ = isset($_GET['__times__']) ? intval($_GET['__times__']) + 1 : 1;
	if($__times__ > 2) {
		return '';
	}
	$url .= (strpos($url, '?') === FALSE ? '?' : '&')."__times__=$__times__";
	return uc_fopen($url, $limit, $post, $cookie, $bysocket, $ip, $timeout, $block);
}

function uc_fopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE) {
	$return = '';
	$matches = parse_url($url);
	!isset($matches['host']) && $matches['host'] = '';
	!isset($matches['path']) && $matches['path'] = '';
	!isset($matches['query']) && $matches['query'] = '';
	!isset($matches['port']) && $matches['port'] = '';
	$host = $matches['host'];
	$path = $matches['path'] ? $matches['path'].($matches['query'] ? '?'.$matches['query'] : '') : '/';
	$port = !empty($matches['port']) ? $matches['port'] : 80;
	if($post) {
		$out = "POST $path HTTP/1.0\r\n";
		$out .= "Accept: */*\r\n";
		//$out .= "Referer: $boardurl\r\n";
		$out .= "Accept-Language: zh-cn\r\n";
		$out .= "Content-Type: application/x-www-form-urlencoded\r\n";
		$out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
		$out .= "Host: $host\r\n";
		$out .= 'Content-Length: '.strlen($post)."\r\n";
		$out .= "Connection: Close\r\n";
		$out .= "Cache-Control: no-cache\r\n";
		$out .= "Cookie: $cookie\r\n\r\n";
		$out .= $post;
	} else {
		$out = "GET $path HTTP/1.0\r\n";
		$out .= "Accept: */*\r\n";
		//$out .= "Referer: $boardurl\r\n";
		$out .= "Accept-Language: zh-cn\r\n";
		$out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
		$out .= "Host: $host\r\n";
		$out .= "Connection: Close\r\n";
		$out .= "Cookie: $cookie\r\n\r\n";
	}
	$fp = @fsockopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout);
	if(!$fp) {
		return '';//note $errstr : $errno \r\n
	} else {
		stream_set_blocking($fp, $block);
		stream_set_timeout($fp, $timeout);
		@fwrite($fp, $out);
		$status = stream_get_meta_data($fp);
		if(!$status['timed_out']) {
			while (!feof($fp)) {
				if(($header = @fgets($fp)) && ($header == "\r\n" ||  $header == "\n")) {
					break;
				}
			}

			$stop = false;
			while(!feof($fp) && !$stop) {
				$data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit));
				$return .= $data;
				if($limit) {
					$limit -= strlen($data);
					$stop = $limit <= 0;
				}
			}
		}
		@fclose($fp);
		return $return;
	}
}

远程同步登录子系统操作之后:

//显示信息
function showmessage($message, $url_forward='', $second=3, $vars=array()) {
	global $_SGLOBAL, $_SCONFIG, $_SC, $channels;

	if(empty($_SGLOBAL['inajax']) && $url_forward && empty($second)) {
		//直接301跳转
		obclean();
		header("HTTP/1.1 301 Moved Permanently");
		header("Location: $url_forward");
	} else {
		if(!defined('IN_SUPESITE_ADMINCP')) {
			$tpl_file = 'showmessage';
			$fullpath = 0;
			include_once(S_ROOT.'./language/message.lang.php');
			if(!empty($mlang[$message])) $message = $mlang[$message];
		} else {
			$tpl_file = 'admin/tpl/showmessage.htm';
			$fullpath = 1;
			include_once(S_ROOT.'./language/admincp_message.lang.php');
			if(!empty($amlang[$message])) $message = $amlang[$message];
		}

		if(isset($_SGLOBAL['mlang'][$message])) $message = $_SGLOBAL['mlang'][$message];
		foreach ($vars as $key => $val) {
			$message = str_replace('{'.$key.'}', $val, $message);
		}
		//显示
		obclean();
		if(!empty($url_forward)) {
			$second = $second * 1000;
			$message .= "<script>setTimeout(\"window.location.href ='$url_forward';\", $second);</script><ajaxok>";
		}

		include template($tpl_file, $fullpath);
		ob_out();
	}
	exit();
}

本文地址:http://www.nowamagic.net/librarys/veda/detail/1497,欢迎访问原出处。

不打个分吗?

转载随意,但请带上本文地址:

http://www.nowamagic.net/librarys/veda/detail/1497

如果你认为这篇文章值得更多人阅读,欢迎使用下面的分享功能。
小提示:您可以按快捷键 Ctrl + D,或点此 加入收藏

大家都在看

阅读一百本计算机著作吧,少年

很多人觉得自己技术进步很慢,学习效率低,我觉得一个重要原因是看的书少了。多少是多呢?起码得看3、4、5、6米吧。给个具体的数量,那就100本书吧。很多人知识结构不好而且不系统,因为在特定领域有一个足够量的知识量+足够良好的知识结构,系统化以后就足以应对大量未曾遇到过的问题。

奉劝自学者:构建特定领域的知识结构体系的路径中再也没有比学习该专业的专业课程更好的了。如果我的知识结构体系足以囊括面试官的大部分甚至吞并他的知识结构体系的话,读到他言语中的一个词我们就已经知道他要表达什么,我们可以让他坐“上位”毕竟他是面试官,但是在知识结构体系以及心理上我们就居高临下。

所以,阅读一百本计算机著作吧,少年!

《人月神话》 弗雷德里克·布鲁克斯 (作者), 汪颖 (译者)

《人月神话》原文:The Mythical Man-Month: The Essays on Software Engineering, 2nd ed.在软件领域,很少能有像《人月神话》一样具有深远影响力并且畅销不衰的著作。Brooks博士为人们管理复杂项目提供了最具洞察力的见解。既有很多发人深省的观点,又有大量软件工程的实践。本书内容来自Brooks博士在IBM公司System/360家族和OS/360中的项目管理经验。该书英文原版一经面世,即引起业内人士的强烈反响,后又译为德、法、日、俄中等多种语言,全球销量数百万册。确立了其在行业内的经典地位。

更多计算机宝库...