我用的是Discuz! X3.1,是比较新的版本,我的服务器环境是FreeBSD 8.2-RELEASE-p9; web服务器为apache;mysql数据库和web服务器在同一台服务器上;安装discuz过程中没有任何错误和警告;安装好之后访问OK,但是和我的网站通信过程中出现用户不能同步的问题,部署过程和排错过程如下:
整合过程:
1,将安装好的论坛下的uc_client,config,data 等复制到自己网站主目录
2,登陆论坛,在管理中心打开ucenter用户管理中心,点开应用程序 添加自己的网站到应用列表中,应用类型选择为其他 ,应用的主URL填写自己网站的主地址;
3,如果通信不成功,最好写上应用IP地址,如果网站和论坛在同一个服务器上,那写上127.0.0.1即可;因为当我们的请求送达服务器时,其实用户同步是服务器和服务器之间的通信;
按照以上步骤操作完成后,网站和论坛的通信已经成功了;下边实现注册登录免激活操作,将自己网站的用户名密码邮箱信息发送到bbs,实现一键跳转登陆;
下边是接收用户信息,实现注册,登陆免激活的代码,
我们自己的网站加一个链接,点击后的 URL为 http://192.168.0.5:8090/login?username=hello&password=123&email=test@qq.com ,下边的loginAction负责处理
public function loginAction(){
$request=$this->getRequest();
$username=$request->get("username");
$userpass=$request->get('password');
$email=$request->get('email');
define('IN_COMSENZ',"");
$domain = "http://192.168.0.5:8090/";
include 'config/config_global.php';
include 'config/config_ucenter.php';
include 'uc_client/client.php';
$uid = uc_user_register($username, $userpass, $email);
if ($uid <= 0) {
if ($uid == -1) {
echo '用户名不合法';
} elseif ($uid == -2) {
echo '包含要允许注册的词语';
} elseif ($uid == -3) {
//echo '正在登入系统...';
} elseif ($uid == -4) {
echo 'Email 格式有误';
} elseif ($uid == -5) {
echo 'Email 不允许注册';
} elseif ($uid == -6) {
echo '该 Email 已经被注册';
} else {
echo '未定义';
}
}
$ucsynlogin="error";
$url='<script>location.href='.$domain.'bbs/forum.php</script>';
list($uid, $username, $userpass, $email) = uc_user_login($username, $userpass);
if ($uid > 0) {
$ucsynlogin = uc_user_synlogin($uid); //如果成功,此处会返回一段js,输出到页面执行后,本地也就写入了cookie,跳转时候也就登陆成功了
echo "正在跳转...";
$url="<script>location.href='http://192.168.0.5:8090/bbs/forum.php';</script>";
echo $ucsynlogin;
echo $url;
} elseif ($uid == -1) {
echo '用户不存在,或者被删除';
} elseif ($uid == -2) {
echo '密码错';
} else {
echo '未定义';
}
// return $this->render("AcmeMspBundle:BBS:login.html.twig",array('url'=>$url,'uid'=>$uid,'js'=>$ucsynlogin));
}
如果发现ucenter 里边已经插入数据,而common_member却没有数据,那是因为注册之后没有激活,所以也没有办法实现跳转登陆,具体解决办法如下:
找到bbs目录下的api里边的uc.php,用一下实现方式替换synlogin函数;具体如下:
function synlogin($get, $post){
global $_G;
if(!API_SYNLOGIN)
return API_RETURN_FORBIDDEN;
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
$cookietime = 31536000;
$uid = intval($get['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);
$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);
}
}
一般正常情况下,通过以上方式就可以实现注册自动登陆一体完成;如果还是无法实现登陆修改如下代码: 自己网站的uc_client 下的client.php
function uc_user_synlogin($uid) {
$uid = intval($uid);
if(@include UC_ROOT.'./data/cache/apps.php') {
if(count($_CACHE['apps']) > 1) {
$return = uc_api_post('user', 'synlogin', array('uid'=>$uid));
} else {
$return = '';
//不管执行if还是else 强制执行将else里边的 $return=''; 改为下边的;有时候确实因为配置问题导致不能执行uc_api_post函数
$return = uc_api_post('user', 'synlogin', array('uid'=>$uid));
}
}
return $return;
}
如果通过以上方式还是存在问题,首先应该一步异步排除php配置allow_url_open = On,扩展是否打开sockets.so,linux防火墙端口是否添加例外,也可以字节写一段php的socket程序,测试一下服务器的环境是否已经支持php的socket.也顺便检查一下以下代码:
在我们网站的uc_client 下的client.php ,这个文件负责和论坛下的uc_server通信,来实现一些列同步操作的;他主要的方式也是通过fsockopen 来模拟http协议实现数据传输的;可以查看client.php 里边的一下函数,稍作适当修改(前提是服务器已经支持socket)
//模拟http请求的socket的实现
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";
}
//可以放开下边一行注释试试
//$host='127.0.0.1'; $ip='127.0.0.1';
if(function_exists('fsockopen')) {
$fp = @fsockopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout);
//如果$fp 操作超时 errno 600 ,应该是服务器IP的问题,如果bbs的web服务器和自己网站的web服务器在同一台服务器,建议使用127.0.0.1 ,让过不必要的阻挡;
} elseif (function_exists('pfsockopen')) {
$fp = @pfsockopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout);
} else {
$fp = false;
}
//在此处调试$fp的值 ,尽量使用print_r($fp);
if(!$fp) {
//有时候会再此处返回 socket却是为null的值
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;
}
}
}
@fclose($fp);
return $return;
}
}
通过修改以上fsockopen函数的 IP直接为127.0.0.1 ,也可以实现通信成功!,(前提是网站和bbs同在一个服务器)
如果ucenter插入用户数据成功,discuz插入用户数据不成功,大部分情况下是以上函数socket通信失败造成的,可以在此处盘查;