网站开发 · 2025年4月23日

排查ecshop2.7.3与discuz X3.1同步登录时问题

环境:Apache/2.2.21 + PHP/5.3.10 + winXP

背景:ecshop2.7.3 打上补丁、discuz X3.1、ucenter1.6 全部utf-8编码实现同步登录、退出、用户创建

 1、在ucenter中看到的是全部通信成功,但就是无法同步登录,注册新用户也可以同步。而且在ecshop登录的时候还会出现400 Bad Request错误


排查ecshop2.7.3与discuz X3.1同步登录时问题插图

让好模板极度郁闷,于是挨个的追踪,一直追踪到ecshop/uc_client/client.php中的uc_fopen函数,大致位于178行。看了下,也没有什么问题。到网上到处搜索,众说纷云,有些好模板还是会直接否定掉的。由于网络文章一堆抄。算了。到这个函数这里,好模板准备记录下,它到底发什么数据出去,又接收到什么怎样的数据才显示出400给好模板。

于是又再次抓包:


排查ecshop2.7.3与discuz X3.1同步登录时问题插图1

结果真让人汗颜,返回是正确的结果,为什么用浏览器登录返回却是不正常的。把这些地址复制到同一浏览器里,结果可以同步登录了。晕倒了。问题确定了,是socket出的问题。于是就用curl试了一下,呵呵,登录同步成功。

if(stripos($return, ‘400 Bad Request’) != false  || empty($return)) {

$return = ”;

$curl = curl_init(); 

curl_setopt($curl, CURLOPT_URL, $url); 

curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER[‘HTTP_USER_AGENT’]); 

if($post) { 

curl_setopt($curl, CURLOPT_POST, 1); 

curl_setopt($curl, CURLOPT_POSTFIELDS, $post); 



if($cookie) { 

curl_setopt($curl, CURLOPT_COOKIE, $cookie); 



curl_setopt($curl, CURLOPT_TIMEOUT, $timeout); 

curl_setopt($curl, CURLOPT_HEADER, 0); 

curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 

$return = curl_exec($curl); 

if (curl_errno($curl)) { 

//echo ‘<pre><b>错误:</b><br />’.curl_error($curl); 



curl_close($curl); 

}

另外,再修正下官方的host,因为好模板这里记录下header的时候,host居然为空的,不知道是不是好模板ucenter配置的问题。

$path = $matches[‘path’] ? $matches[‘path’].($matches[‘query’] ? ‘?’.$matches[‘query’] : ”) : ‘/’;

$host = empty($matches[‘host’]) ? dirname($path) : $matches[‘host’];

大约位于184行。

2、上面可以解决ecshop登录,discuz也登录,但ecshop退出,discuz却保持登录状态

修改ecshop/includes/lib_common.php

$res = call_user_func_array($func, empty($params) ? array(‘0’) : $params);    完成上面2步以后,可以实现ecshop登录、退出后,discuz也跟着做同样的动作。

3、一定要将ecshop/uc_client与discuzX/uc_client保持一致

将ecshop/uc_client/data/cache/apps.php与discuzX/uc_client/data/cache/apps.php内容保持一致

将ecshop/uc_client/client.php与discuzX/uc_client/client.php 内容保持一致 

4、从ecshop登录,discuz退出,会出现ecshop没有退出的现象。由于cookie值域的问题。因为discuz在退出的时候会用JS调用到这个api来同步退出。

修改ecshop/api/uc.php中的set_cookie函数,约408行

setcookie(‘ECS[user_id]’, ”, $time, $GLOBALS[‘cookie_path’], $GLOBALS[‘cookie_domain’]);

setcookie(‘ECS[username]’, ”, $time, $GLOBALS[‘cookie_path’], $GLOBALS[‘cookie_domain’]);

setcookie(‘ECS[email]’, ”, $time, $GLOBALS[‘cookie_path’], $GLOBALS[‘cookie_domain’]);

5、ecshop/includes/modules/integrates/ucenter.php

ucenter($cfg)函数(约75行)$this->is_ecshop = 1;后面加入:

$this->cookie_path = $cfg[‘cookie_path’];

$this->cookie_domain = $cfg[‘cookie_domain’];

第463行set_cookie($username=”)函数加入域范围

/* 摧毁cookie */

$time = time() – 3600;

setcookie(“ECS[user_id]”, ”, $time, $this->cookie_path, $this->cookie_domain); 

setcookie(“ECS[password]”, ”, $time, $this->cookie_path, $this->cookie_domain);

OK,至此ecshop和discuz就可以完全注册登录退出同步了。

PS:如果discuz X3.1在退出时提示:Discuz!  System Error 您当前的访问请求当中含有非法字符,已经被系统拒绝

 可以下载官方的语言包覆盖就行了l 注意此语言包为GBK版

目前,只有注册并同步登录未实现:参考了一下网上的代码,但好模板这里并没有成功

discuz/api/uc.php中synlogin函数第191行

if(($member = getuserbyuid($uid, 1))) {

dsetcookie(‘auth’, authcode(“$member[password]\t$member[uid]”, ‘ENCODE’), $cookietime);

}else{

//下面为增加部分

$username = $get[‘username’]; 

$password = md5(time().rand(100000, 999999));

$email = $get[’email’];

$ip = $_SERVER[‘REMOTE_ADDR’];

$time = time(); 

$userdata = array(

‘uid’ => $uid,

‘username’ => $username,

‘password’ => $password,

’email’ => $email,

‘adminid’ => 0,

‘groupid’ => 10,

‘regdate’ => $time,

‘credits’ => 0,

‘timeoffset’ => 9999

);

DB::insert(‘common_member’, $userdata);

$status_data = array(

‘uid’ => $uid,

‘regip’ => $ip,

‘lastip’ => $ip,

‘lastvisit’ => $time,

‘lastactivity’ => $time,

‘lastpost’ => 0,

‘lastsendmail’ => 0,

);

DB::insert(‘common_member_status’, $status_data);

DB::insert(‘common_member_profile’, array(‘uid’ => $uid));

DB::insert(‘common_member_field_forum’, array(‘uid’ => $uid));

DB::insert(‘common_member_field_home’, array(‘uid’ => $uid));

DB::insert(‘common_member_count’, array(‘uid’ => $uid)); 

$query = DB::query(“SELECT uid, username, password FROM “.DB::table(‘common_member’).” WHERE uid=’$uid'”);

if($member = DB::fetch($query)) {

dsetcookie(‘auth’, authcode(“$member[password]\t$member[uid]”, ‘ENCODE’), $cookietime);

}

}