首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP cURL 獲取 QQ 用戶資訊遭遇 SSL 憑證錯誤的解決方案

     編輯:PHP 相關知識

PHP cURL 獲取 QQ 用戶資訊遭遇 SSL 憑證錯誤的解決方案

在實現 QQ 登入回調時,使用 file_get_contents 無法正確獲取資料,改用 cURL 卻遇到 SSL 憑證驗證失敗。本文記錄問題排查過程與解決方案,供遇到相同問題的開發者參考。

問題現象

  • ECMall 商城接入 QQ 登入,回調階段需獲取用戶資訊
  • file_get_contents 請求 HTTPS 介面無回應或資料不全
  • 改用 cURL 後出現:SSL certificate problem: unable to get local issuer certificate

根本原因

cURL 預設啟用 SSL 對等驗證(CURLOPT_SSL_VERIFYPEER = true),需要本機有有效的 CA 憑證包(cacert.pem)才能驗證伺服器憑證鏈。若 PHP 環境未配置或憑證過期,驗證會失敗。

快速解決方案(開發/測試環境)

暫時關閉 SSL 驗證:

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://graph.qq.com/user/get_user_info?...');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

// 關閉 SSL 對等驗證與主機名驗證(僅限測試環境)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

$response = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'cURL 錯誤: ' . curl_error($ch);
} else {
    echo $response;
}
curl_close($ch);
?>

生產環境正規解決方案

方案一:配置 CA 憑證包(推薦)

  1. 下載最新 CA 憑證:cacert.pem
  2. 放置於伺服器可讀路徑,如 /etc/ssl/certs/cacert.pem 或 /usr/local/php/cacert.pem
  3. 修改 php.ini:
; 指定 CA 憑證檔案路徑
curl.cainfo = "/usr/local/php/cacert.pem"
openssl.cafile = "/usr/local/php/cacert.pem"
  • 重啟 PHP-FPM / Apache 使配置生效
  • 方案二:程式碼中指定憑證路徑

    curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cacert.pem');
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    

    另一種傳聞方案(經測試無效)

    網上有建議設定 CURLOPT_HTTPHEADER => ['Expect:'] 解決,實測對憑證驗證錯誤無效,該選項主要針對 100 Continue 行為。

    完整 QQ 獲取用戶資訊範例

    <?php
    function getQQUserInfo($accessToken, $openId, $appId)
    {
        $url = 'https://graph.qq.com/user/get_user_info';
        $params = [
            'access_token' => $accessToken,
            'oauth_consumer_key' => $appId,
            'openid' => $openId,
            'format' => 'json'
        ];
        $queryString = http_build_query($params);
    
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url . '?' . $queryString);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);  // 生產環境必須開啟
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        // 若未在 php.ini 設定全域 cacert,可在此指定
        // curl_setopt($ch, CURLOPT_CAINFO, '/usr/local/php/cacert.pem');
    
        $response = curl_exec($ch);
        $errNo = curl_errno($ch);
        $errMsg = curl_error($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
    
        if ($errNo) {
            error_log("QQ用戶資訊獲取失敗: [$errNo] $errMsg, HTTP: $httpCode");
            return false;
        }
    
        $data = json_decode($response, true);
        if (isset($data['ret']) && $data['ret'] != 0) {
            error_log("QQ API 返回錯誤: " . json_encode($data));
            return false;
        }
        return $data;
    }
    ?>

    最佳實踐總結

    • 開發階段可暫時關閉驗證快速調通流程,但務必在上線前恢復驗證
    • 生產環境必須配置有效 CA 憑證,防止中間人攻擊,保障用戶資料安全
    • 定期更新 cacert.pem(建議每季度),避免根憑證過期導致驗證失敗
    • 封裝通用 HTTP 客戶端類,統一處理 SSL、逾時、重試、日誌,避免分散配置

    SSL 憑證驗證是 HTTPS 安全的基石,正確配置而非單純關閉,才是專業開發者的選擇。

    1. 上一篇文章:
    2. 下一篇文章:
    Copyright © 程式碼之家 All Rights Reserved