Discuz! 作為經典 PHP 論壇系統,其 UCenter 機制提供了跨應用的單點登入(SSO)能力。本文詳細說明 UCenter 通訊原理、配置要點、API 調用流程、同步登入/登出實作、常見坑點與現代化替代方案,助你快速將既有 PHP 系統與 Discuz! 整合。
UC_APPID。UC_CONNECT=mysql:直接讀寫 UCenter 資料庫(高效能、需同網段、資料庫帳號權限)。UC_CONNECT= (空):**API 模式**,透過 HTTP 請求 UC_API/uc.php(跨網段、安全、標準)。uc.php 完成 Session/Cookie 同步。登入 UCenter 管理後台 → 應用管理 → 新增應用:
https://your-app.comUC_KEY:必須與客戶端配置完全一致config.inc.php(或 uc_client/config.inc.php)<?php
// UCenter 客戶端配置
define('UC_CONNECT', 'mysql'); // 或 '' 使用 API 模式
define('UC_DBHOST', 'localhost');
define('UC_DBUSER', 'ucenter_user');
define('UC_DBPW', 'secure_password');
define('UC_DBNAME', 'ucenter');
define('UC_DBCHARSET', 'utf8mb4');
define('UC_DBTABLEPRE', 'ucenter.uc_');
define('UC_KEY', 'your_very_long_random_key_here'); // 必須與 UCenter 後台一致
define('UC_API', 'https://ucenter.yourdomain.com'); // UCenter 入口 URL
define('UC_CHARSET', 'utf-8');
define('UC_IP', ''); // API 模式下若域名解析有問題可填 IP
define('UC_APPID', 3); // UCenter 後台分配的應用 ID
define('UC_PPP', 20); // 每頁數量
// Cookie 設定(跨域同步需注意 domain 設定)
$_UC = [];
$_UC['cookiedomain'] = '.yourdomain.com'; // 共用根域名才能跨子域同步 Cookie
$_UC['cookiepath'] = '/';
$_UC['cookiepre'] = 'uc_';
$_UC['cookietime'] = 31536000; // 1 年
<?php
require_once __DIR__ . '/uc_client/client.php'; // 根據實際路徑調整
<?php
// login.php
// 1. 驗證用戶名密碼(呼叫 UCenter 驗證)
list($uid, $username, $password, $email) = uc_user_login($_POST['username'], $_POST['password']);
if ($uid > 0) {
// 登入成功
// 2. 產生同步登入代碼(包含其他應用的 JS)
$synlogin = uc_user_synlogin($uid);
// 3. 建立本地 Session
$_SESSION['uid'] = $uid;
$_SESSION['username'] = $username;
// ... 其他本地登入邏輯
// 4. 輸出同步代碼(關鍵:必須輸出到瀏覽器執行!)
echo $synlogin;
// 5. 跳轉或回傳成功
echo '<script>window.location.href="/dashboard";</script>';
exit;
} elseif ($uid == -1) {
echo '用戶不存在或被刪除';
} elseif ($uid == -2) {
echo '密碼錯誤';
} else {
echo '未知錯誤';
}
<?php
// register.php
$uid = uc_user_register($_POST['username'], $_POST['password'], $_POST['email']);
if ($uid > 0) {
// 註冊成功,同步登入
$synlogin = uc_user_synlogin($uid);
echo $synlogin;
echo '<script>alert("註冊成功"); window.location.href="/";</script>';
} elseif ($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 '註冊失敗';
}
<?php
// logout.php
// 1. 取得同步登出代碼
$synlogout = uc_user_synlogout();
// 2. 銷毀本地 Session
session_destroy();
// 或
$_SESSION = [];
if (ini_get('session.use_cookies')) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
}
// 3. 輸出同步代碼
echo $synlogout;
echo '<script>window.location.href="/";</script>';
若無法直連資料庫,需實作 api/uc.php 接收 UCenter 回調:
<?php
// api/uc.php
define('API_DELETEUSER', 1);
define('API_RENAMEUSER', 1);
define('API_GETTAG', 0);
define('API_SYNLOGIN', 1); // 同步登入
define('API_SYNLOGOUT', 1); // 同步登出
define('API_UPDATEPW', 1); // 更新密碼
define('API_UPDATEBADWORDS', 0);
define('API_UPDATEHOSTS', 0);
define('API_UPDATEAPPS', 1);
define('API_UPDATECLIENT', 1);
define('API_UPDATECREDIT', 0);
define('API_GETCREDITSETTINGS', 0);
define('API_GETCREDIT', 0);
define('API_UPDATECREDITSETTINGS', 0);
require_once '../uc_client/client.php';
// uc.php 會自動處理 $_GET['code'] 解密、分派對應函式
// 你需要實作以下函式(在同目錄下建立 api/ 目錄):
// function synlogin($get, $post) { /* 建立本地 session/cookie */ }
// function synlogout($get, $post) { /* 銷毀本地 session/cookie */ }
// function updatepw($get, $post) { /* 更新本地密碼 */ }
// function deleteuser($get, $post) { /* 刪除本地用戶 */ }
// ... 參考 uc_client/model/base.php
若 UCenter 在 ucenter.example.com,應用在 app.example.com:
$_UC['cookiedomain'] = '.example.com';(注意前綴點)session.cookie_domain = .example.com(php.ini 或 session_set_cookie_params())header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');session_set_cookie_params(['samesite' => 'Lax']) 或 None(需 Secure)| 現象 | 可能原因 | 解決 |
|---|---|---|
| 同步代碼輸出但不生效 | JS 錯誤、域名不匹配、Cookie 未送達 | F12 Console 看錯誤、檢查 Cookie Domain、Network 看請求是否發出 |
| UC_KEY 不正確 | 雙端金鑰不一致、編碼問題 | 重新生成 32 字元隨機鍵,雙端同步更新 |
| API 模式通訊失敗 | 防火牆阻擋、DNS 解析、SSL 憑證驗證失敗 | 允許出站 80/443、curl -v 測試、curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false)(測試用) |
| 登入後刷新掉線 | Session 儲存路徑權限、Session ID 重生成 | 檢查 session.save_path 權限、避免每請求 session_regenerate_id() |
| 同步登出無效 | 未輸出 uc_user_synlogout() 返回的 JS | 確認 echo $synlogout; 在輸出 |
UCenter 屬於早期架構,新專案建議採用標準協定:
Discuz! UCenter 雖屬經典架構,但在既有生態整合中仍具實用價值。掌握其通訊流程、配置細節、同步機制,並建立向現代身分認證標準遷移的路線圖,才能在維護舊系統與建設新架構間取得平衡。