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

PHP cURL 發送 HTTPS 請求:憑證驗證失敗解決方案與最佳實踐

     編輯:PHP 綜合知識

cURL 存取 HTTPS API 時常遇到「SSL certificate problem: certificate verify failed」錯誤。本文分析憑證驗證機制、提供開發/生產環境差異化解決方案、說明安全性風險與正確部署流程。

錯誤現象

SSL certificate problem, verify that the CA cert is OK. 
Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

快速解決 (僅限開發/測試環境)

<?php
$ch = curl_init('https://api.example.com/endpoint');

// ⚠️ 關閉對等憑證驗證 (不驗證伺服器身份)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

// 仍檢查 SSL 加密演算法是否存在 (保留最基本防護)
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 2 = 檢查 CN 是否存在

// ... 其他設定
$response = curl_exec($ch);
?>

生產環境正確做法:部署 CA 憑證

步驟 1:取得 CA 憑證包

# 方式 A:從系統套件安裝 (推薦)
# CentOS/RHEL
yum install ca-certificates

# Ubuntu/Debian
apt-get install ca-certificates

# 方式 B:使用 Mozilla 官方 CA 包 (cURL 官方推薦)
wget https://curl.se/ca/cacert.pem -O /etc/ssl/certs/cacert.pem

步驟 2:配置 PHP/cURL 使用 CA 憑證

<?php
$ch = curl_init('https://api.example.com/endpoint');

// 指定 CA 憑證檔案路徑
curl_setopt($ch, CURLOPT_CAINFO, '/etc/ssl/certs/cacert.pem');
// 或指定 CA 目錄 (需經 c_rehash 處理)
curl_setopt($ch, CURLOPT_CAPATH, '/etc/ssl/certs/');

// 正常驗證模式
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);

步驟 3:php.ini 全域配置 (一次設定,全域生效)

; php.ini
[curl]
; 指定預設 CA 檔案
curl.cainfo = "/etc/ssl/certs/cacert.pem"

[openssl]
; OpenSSL 擴展預設 CA
openssl.cafile = "/etc/ssl/certs/cacert.pem"

完整封裝函式 (含錯誤處理)

<?php
/**
 * 安全的 HTTPS 請求封裝
 * @param string $url 請求 URL
 * @param array $data POST 資料
 * @param array $header 自訂標頭
 * @param int $timeout 逾時秒數
 * @return string|false 回應內容或 false
*/
function curl_https($url, array $data = [], array $header = [], $timeout = 30) {
    $ch = curl_init();
    
    // 基礎設定
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => $timeout,
        CURLOPT_POST => !empty($data),
        CURLOPT_POSTFIELDS => $data ? http_build_query($data) : '',
        CURLOPT_HTTPHEADER => $header ?: ['Content-Type: application/x-www-form-urlencoded'],
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS => 5,
        
        // SSL 安全設定 (生產環境標準)
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2,
        // CURLOPT_CAINFO => '/path/to/cacert.pem', // 若 php.ini 未設定則需指定
    ]);
    
    // 執行請求
    $response = curl_exec($ch);
    
    // 錯誤處理
    if ($response === false) {
        $errorNo = curl_errno($ch);
        $errorMsg = curl_error($ch);
        error_log("cURL 錯誤 [$errorNo]: $errorMsg | URL: $url");
        curl_close($ch);
        return false;
    }
    
    // 檢查 HTTP 狀態碼
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    if ($httpCode < 200 || $httpCode >= 300) {
        error_log("HTTP 錯誤 [$httpCode]: $url");
    }
    
    curl_close($ch);
    return $response;
}

// 使用範例
$response = curl_https('https://api.example.com/v1/users', [
    'action' => 'create',
    'name' => 'John Doe'
], [
    'Authorization: Bearer YOUR_TOKEN',
    'Accept: application/json'
]);

常見憑證問題排查清單

安全性警示

⚠️ 絕對不要在生產環境使用 CURLOPT_SSL_VERIFYPEER => false
這會使中間人攻擊 (MITM) 變得極其簡單,攻擊者可攔截、竄改、盜取所有傳輸資料 (含 Token、個資、金流資訊)。正確做法是部署正確的 CA 憑證。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
問題原因解決方案
自簽憑證開發/測試環境使用自我簽署憑證將自簽 CA 加入系統信任存儲,或 CURLOPT_CAINFO 指定
憑證鏈不完整伺服器未正確配置中繼憑證聯繫 API 提供方修正,或暫時關閉驗證 (僅測試)
主機名不符CN/SAN 不包含請求的域名檢查 DNS/Hosts,或 CURLOPT_SSL_VERIFYHOST=0 (危險)
憑證過期伺服器憑證已過期聯繫提供方更新,切勿長期忽略
系統 CA 過舊作業系統 ca-certificates 套件版本過舊更新套件或手動更新 cacert.pem