discuz 用戶整合ucenter的 fsockopen 通信問題解決

     我用的是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 protected] ,下邊的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通信失敗造成的,可以在此處盤查;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章