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