discuz 用户整合ucenter的 fsockopen 通信问题解决

来源:互联网 发布:java培训费一般多少 编辑:程序博客网 时间:2024/05/28 05:16

     我用的是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通信失败造成的,可以在此处盘查;


0 0
原创粉丝点击