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

PHP cURL 訪問 HTTPS 完整指南:證書驗證等級、CA 憑證配置與常見錯誤排查

     編輯:PHP 綜合知識

核心函數封裝

<?php
/**
 * cURL POST 請求(支援 HTTPS 多級驗證)
 * @param string $url       目標 URL
 * @param array  $data      POST 欄位
 * @param int    $timeout   總超時秒數
 * @param bool   $strictSSL true=嚴格驗證CA,false=寬鬆模式
 * @return string|false 響應內容或 false
 */
function curlPost($url, $data = [], $timeout = 30, $strictSSL = true) {
    $cacert = __DIR__ . '/cacert.pem'; // CA 根憑證路徑
    $isHttps = strncasecmp($url, 'https://', 8) === 0;

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL            => $url,
        CURLOPT_TIMEOUT        => $timeout,
        CURLOPT_CONNECTTIMEOUT => $timeout - 2,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => $data,
        CURLOPT_HTTPHEADER     => ['Expect:'], // 避免大數據觸發 100-continue
    ]);

    if ($isHttps) {
        if ($strictSSL) {
            // === 嚴格模式:僅信任 CA 簽發 ===
            curl_setopt_array($ch, [
                CURLOPT_SSL_VERIFYPEER => true,  // 驗證對端憑證
                CURLOPT_CAINFO         => $cacert, // 指定 CA 束
                CURLOPT_SSL_VERIFYHOST => 2,       // 驗證 CN/SAN 匹配域名
            ]);
        } else {
            // === 寬鬆模式:信任任何憑證(僅測試/內網) ===
            curl_setopt_array($ch, [
                CURLOPT_SSL_VERIFYPEER => false, // 不驗證憑證來源
                CURLOPT_SSL_VERIFYHOST => 1,     // 僅檢查是否有 CN
            ]);
        }
    }

    $response = curl_exec($ch);
    if ($response === false) {
        error_log('cURL Error: ' . curl_error($ch) . ' | URL: ' . $url);
    }
    curl_close($ch);
    return $response;
}
?>

三種驗證等級詳解

等級CURLOPT_SSL_VERIFYPEERCURLOPT_SSL_VERIFYHOST適用場景
嚴格(生產標準)true2公開 API、支付網關、第三方可信服務
中等true1內網自簽憑證、已導入私有 CA
寬鬆(僅加密不驗證)false0/1開發測試、內網無 CA 環境、臨時繞過

警告:生產環境嚴禁使用寬鬆模式,將面臨中間人攻擊風險。

CA 憑證檔案 (cacert.pem) 獲取

  • 官方來源:https://curl.se/ca/cacert.pem(Mozilla 根憑證庫定期更新)
  • 系統內建:/etc/ssl/certs/ca-certificates.crt (Debian/Ubuntu) 或 /etc/pki/tls/certs/ca-bundle.crt (CentOS/RHEL)
  • PHP 內建:PHP 5.6+ 可直接用 openssl_get_cert_locations()['default_cert_file']
$cacert = openssl_get_cert_locations()['default_cert_file'] ?? __DIR__ . '/cacert.pem';

常見錯誤碼與排查

進階:雙向 TLS (mTLS) / 客戶端憑證

curl_setopt_array($ch, [
    CURLOPT_SSLCERT => __DIR__ . '/client.pem',   // 客戶端憑證+私鑰
    CURLOPT_SSLKEY  => __DIR__ . '/client.key',   // 若 client.pem 未含私鑰
    CURLOPT_KEYPASSWD => 'keypassword',           // 私鑰密碼
]);

效能優化提示

  • 複用句柄:長生命週期服務中重複使用 $ch,配合 curl_reset()
  • 連線池:Swoole/Guzzle 內建連線池,避免重複 TCP/TLS 握手
  • HTTP/2:curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0)
  • 非阻塞並發:curl_multi 或 Swoole 協程客戶端
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
錯誤原因解決
SSL certificate problem: self signed certificate對端用自簽憑證,CA 不信任導入對端 CA 到 cacert.pem,或寬鬆模式(僅測試)
SSL: certificate subject name does not match target host name憑證 CN/SAN 不包含請求域名檢查域名拼寫、是否走 CDN/IP 直連、要求對端補全 SAN
SSL connect error / handshake failureTLS 版本不支援(如僅支援 TLS 1.0)curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2)
Operation timed out防火牆攔截、目標 IP 被封、MTU 問題檢查網路連通性、抓包分析