`

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.php

get过来的参数明显是?__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
分享到:
评论

相关推荐

    tp3.2和discuz同步登陆代码

    总之,"tp3.2和discuz同步登陆代码"的实现是一个涉及跨系统交互和用户身份验证的复杂过程,需要对ThinkPHP和Discuz! 的API有深入理解,同时也需要关注安全性和用户体验。通过这种方式,开发者可以构建出更一体化的...

    源码!整合discuz与网站的同步登录

    你可以通过分析这段代码,了解如何将主站的登录状态同步到Discuz!,以及如何处理用户的身份验证。 总之,整合Discuz!与网站的同步登录是一项技术性较强的工作,涉及到前后端交互、API调用、安全策略等多个方面。...

    Discuz与ThinkPHP同步登录

    《Discuz与ThinkPHP同步登录实现详解》 在互联网应用开发中,用户登录系统的统一管理是常见的需求。本文将深入探讨如何实现Discuz论坛系统与基于ThinkPHP框架的应用之间的同步登录,帮助开发者理解和掌握这一技术。...

    discuz7.x同步登录退出修改密码

    - 同步登录是指用户在一个应用或网站登录后,其他关联的应用或子系统也会自动登录。在 Discuz! 7.x 中,这通常是通过统一的身份验证服务实现的,可能涉及到Cookie、Session或者Token机制。 - 当用户在主论坛成功...

    ucenter,uchome,discuz同步注册免激活同步登录

    这些文件可能包含了实现同步登录和注册的关键代码。在进行此类操作前,建议先备份原有文件,以防止意外情况导致系统无法正常运行。 文件名"同步注册免激活同步登录"可能包含了一些修改过的PHP脚本或配置文件,例如...

    discuz免激活同步登入代码修改方法(discuz同步登录)

    标题中的“discuz免激活同步登入代码修改方法”是指在Discuz论坛系统中,通过修改特定的代码实现用户无需激活账号就能直接进行同步登录的方法。这个方法主要适用于Discuz! X3版本,理论上也适用于Discuz! X2.5版本。...

    discuz7.2同步登录退出修改密码

    7.2中,实现同步登录的关键是通过Session管理和Cookie来跟踪用户状态。系统会将用户登录信息存储在服务器端的Session中,并在客户端设置一个与Session关联的Cookie。当用户在其他页面或应用中请求时,服务器通过...

    脱离discuz; 获取discuz登录信息程序 适合于网站和discuz登录整合

    ~ ... 类似的代码登录;... 可以嵌入自己的网站代码里实现同步登录。 也可以独立使用注释明确。 3、感谢我自己supFire, 希望大家得到启示, 写出更好的文件共享出来, 也可以写出类似的discuzNT登录整合代码。

    java整合discuz论坛同步注册同步登录资源打包

    java整合discuz论坛同步注册同步登录资源打包,供大家参考参考。

    完美解决shopex和UC1.6同步登录

    7. **代码优化**:为了保证系统的稳定性和性能,同步登录的实现应该尽可能地减少不必要的请求,避免资源浪费。 8. **测试和部署**:完成开发后,需要进行详尽的测试,包括单元测试、集成测试和性能测试,确保在不同...

    Discuz 自动同步登陆通达OA的完美解决办法

    Discuz 自动同步登陆通达OA的完美解决办法,自己看了一下UCenter、Discuz同步登陆的机制,提炼出了以下用于同步登陆Discuz的代码

    discuz同步登陆程序

    ### Discuz同步登录程序解析 #### 一、概述 本文主要介绍了如何实现Discuz与个人网站之间的同步登录功能。Discuz是一款非常流行的论坛系统,它提供了丰富的插件和API接口来帮助开发者进行二次开发和扩展功能。其中...

    Discuz(PHP)论坛和WebSite的同步登录

    主要实现网站登录时能够同步登录Discuz(PHP)论坛,同时实现同步注册、修改、用户删除、登出等功能,网站引用DS.Web.UCenter.dll即可,并附带dll的源码和UCenter的配置说明文档。

    discuz注册同步单点登录

    在本文中,我们将探讨如何实现Discuz论坛系统的注册同步单点登录功能。这一功能对于多应用集成的环境尤其重要,因为它确保了用户在一个系统注册或登录后,可以无缝地在所有关联子系统中自动登录,提高用户体验。 ...

    discuz 第三方 应用 利用 Email 同步 登录

    修改其登录API,达到用email登录的效果(之前的是uid和username) II.注意: 1.确保 UCenter 版本为 1.6.0 2.确保应用于UCenter通信成功,且可以使用API III.使用方法: 1.拷贝下载的文件到应用程序的uclient目录...

    Discuz 自动同步登陆的完美解决办法

    综上所述,解决Discuz自动同步登录的问题需要深入理解UCenter的工作原理、Cookie管理、加密解密机制以及环境适应性,同时在开发过程中进行详尽的测试,确保在各种环境下都能正常工作。对于开发者来说,熟悉这些知识...

    Discuz_X3.1和第三方应用同步登陆、登出

    【标题】"Discuz_X3.1与第三方应用同步登录、登出"涉及到的是网站论坛系统Discuz! X3.1版本与外部应用程序之间用户身份验证的集成问题。这一功能使得用户在一个平台上登录后,无需在其他关联的应用上再次输入用户名...

    discuz论坛源代码

    《Discuz论坛源代码详解及应用指南》 Discuz是一款广泛应用的开源社区论坛软件,以其强大的功能和灵活性深受广大站长喜爱。本篇文章将深入解析Discuz论坛源代码,旨在帮助开发者更好地理解和掌握这款社区平台的核心...

    Discuz!实用代码大全,

    Discuz!实用代码大全 Discuz!是一款流行的论坛软件,提供了丰富的标签系统,帮助用户快速格式化帖子内容。在本文中,我们将介绍Discuz!中的常用代码,帮助初学者快速上手。 1. 字体加粗 代码:[b]字体加粗[/b] ...

Global site tag (gtag.js) - Google Analytics