discuz 同步登录 代码浅析 [转载]

安装ucenter;安装discuz,自动加载到ucenter并通信成功;再尝试把ucenter里的例子部署到ucenter通信,叫uclogion吧,想从uclogion登录,discuz会同步登录,直接把config.inc.php里的////通信相关全部注释,把ucenter里生成的”应用的 UCenter 配置信息”加到config.inc.php后面;通信不成功,别急;参考下 http://www.discuz.net/thread-1388614-1-1.html出错虽然不是在同一地方,但给我帮助很大了,最后结果;是config.inc.php加个$database = ‘mysql’;就通信成功;好了;环境有了,开始我们的代码分板吧!在ucenter里的登录页面写的很清楚 //生成同步登录的代码 $ucsynlogin = uc_user_synlogin($uid); //$uid 会员信息的ID;echo一下;居然什么也没打印出来,别急,右击看下源文件,一串JS;基本原理明白了:是uclogion里的JS调用discuz的接口生成跨域的cookie;实现登录登录;当然当有多个应用需要同步时会生成多串JS去调用不同的应用接口生成相应跨域的cookie;继续按住crul 把相关函数找出来;在uclogion/uc_client/client.php里的function uc_user_synlogin($uid) {$uid = intval($uid);$return = uc_api_post(‘user’, ‘synlogin’, array(‘uid’=>$uid));return $return;}/*** */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);}//加密post数据;在同步时也就用UC_ket加密,再在ucenter解密function uc_api_input($data) {$s = urlencode(uc_authcode($data.’&agent=’.md5($_SERVER[‘HTTP_USER_AGENT’]).”&time=”.time(), ‘ENCODE’, UC_KEY));return $s;}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);}………………………………………………………………………………………………………………………………………最后追踪到就是个核心的发起请求的函数了;发起请求的函数用的是fsockopen;最后数据是怎样post过去的,也就是$out这个变量内容起的作用了;简单点的就是知道是post到哪个地址去;我们echo下$url得到http://127.0.0.1/ucenter/index.php?__times__=1/*** 发起socket请求,返回请求结果;</p> * 在同步时请求结果一般是N串script字符串,* 用于种下各应用cookie实现同步登录*/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 ”;} 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; } } } $return; @fclose($fp); return $return;}}上面是在uclogion里也就是第一个应用登录时怎样调用ucenter的接口相关的函数————————————————-在上面echo $url http://127.0.0.1/ucenter/index.php?__times__=1我们直接找到ucenter的index.phpget过来的参数明显是?__times__=1;那么还有post过来的参数;我们直接在入口处就把他print一下;echo “<pre>”;print_r($_POST);再一次在uclogion是尝试登录;得到这Array( [m] => user [a] => synlogin [inajax] => 2 [release] => 20090121 [input] => 2e26ADne+3AM5QckfdoMJiGhwpzfoM9xQOqmCsbT0p+d8Y/uMSpKjP2CJk3/2HpMsAnfMuiTjNAG+YLOHQD2uMf+b/VQbKOqGKy7Qmbah5aKKsHilzyQepU [appid] => 2)结合下上面的uc_api_requestdata函数,基本上知道各个参数的函义m是执行的模块,a是执行的方法; release是cookie的过期时间; input 明显是登录用户的数据,其实也就是用户的uid过来的;appid是提交应用的id;在ucenter里的index.php里有; $classname = $m.’control’;$control = new $classname();$method = ‘on’.$a;把上面的echo出来;也就明白了你在调用了那个类跟方法了://同步类名usercontrol 方法onsynlogin在index.php最后返回是下面;也就是对面的JS代码;echo $data = $control->$method();function onsynlogin() { $this->init_input(); $uid = $this->input(‘uid’); if($this->app[‘synlogin’]) { if($this->user = $_ENV[‘user’]->get_user_by_uid($uid)) { $synstr = ”; //遍历应用生成对应的script foreach($this->cache[‘apps’] as $appid => $app) { if($app[‘synlogin’] && $app[‘appid’] != $this->app[‘appid’]) { $synstr .= ‘<script type=”text/javascript” src=”‘.$app[‘url’].’/api/uc.php?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; } } return ”;}以后是ucenter各个应用登录后怎样生成其它对应的的JS(或许取个名字好理解点:叫”JScookie通行证”吧);ulogion登录后同时过ucente获得jscookie通行证去同步登录其它ucenter的注册应用;———————————————————————————再来观察下那段JScookie通行证吧;<script type=”text/javascript” src=”http://127.0.0.1/bbs/api/uc.php?time=1260777552&code=0105TuJc7mAGVHAKhj%2FsfrNkPxwsLBBqOZcqBkRx0mZmEtPCKYGfZ32nog3gmS1yc6hqsyqD8FgxsoKfXJE2QkygQT3%2F25aZ%2BnuMD5ryzjZWLOSeIAYXgGgYOJHHRYosz458eo06bPSI1cAmb6Dgx8THR0u9mNpdHGdi3%2BsiHw” reload=”1″></script>知道了是接口文件是discuz的api/uc.php下;ctrl+f找一下 synlogin 很快找到180行 elseif($action == ‘synlogin’) {里面的核心代码也就是header(‘P3P: CP=”CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR”‘);这个头信息发送后就强制了浏览器允许跨域注册cookie;紧接着是像我们平时setcookie一样;discuz 封装了下个dsetcookie来setcookie;大家可以找下相关的跨域setcookie的资料看看;关于同步登录的相关文章还有这篇,说的比我好多了,有图说明;http://hi.baidu.com/e_polo/blog/item/321a7b99f69f66026e068c8c.html 对困难的回答是胜利,对胜利的回答是谦逊。

discuz 同步登录 代码浅析 [转载]

相关文章:

你感兴趣的文章:

标签云: