早期常見寫法直接關閉 SSL 驗證(CURLOPT_SSL_VERIFYPEER = false),雖能通訊但等同「裸奔」,中間人攻擊風險極高。本文系統梳理 HTTPS 請求的三種驗證層級與正確姿勢。
function curlPost(string $url, array $data = [], int $timeout = 30, bool $strictSSL = true): string
{
$cacert = __DIR__ . '/cacert.pem'; // CA 根憑證路徑
$isSSL = strncmp($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 ($isSSL) {
if ($strictSSL) {
// 嚴格模式:僅信任 CA 簽發、驗證域名匹配
curl_setopt_array($ch, [
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_CAINFO => $cacert,
CURLOPT_SSL_VERIFYHOST => 2, // 檢查 CN/SAN 與主機名匹配
]);
} else {
// 寬鬆模式:信任任何憑證,僅檢查是否有域名欄位
curl_setopt_array($ch, [
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => 1,
]);
}
}
$ret = curl_exec($ch);
// 失敗時可用 curl_error($ch) 診斷
curl_close($ch);
return $ret;
}
| 層級 | CURLOPT_SSL_VERIFYPEER | CURLOPT_SSL_VERIFYHOST | CURLOPT_CAINFO | 適用場景 |
|---|---|---|---|---|
| 嚴格(推薦生產) | true | 2 | CA 根憑證路徑 | 目標站使用正規 CA 簽發憑證(DigiCert、Let's Encrypt、GlobalSign 等) |
| 中等(僅驗證域名) | false | 1 | 不需要 | 自簽憑證、內網測試環境、開發階段臨時繞過 |
| 完全關閉(極不推薦) | false | 0 | 不需要 | 極少數舊系統相容,**生產環境嚴禁** |
瀏覽器內建主流 CA 公鑰清單。cacert.pem 即打包這些公鑰的 PEM 檔,可從 cURL 官網 下載最新版,定期更新。
憑證中的「主體替代名稱」擴展包含合法域名。VERIFYHOST=2 會同時檢查 CN 與 SAN 是否匹配請求主機名。
cacert-custom.pem。CURLOPT_CAINFO => __DIR__.'/cacert-custom.pem'。VERIFYPEER=true,安全性不打折。SSL certificate problem: self signed certificate → 未提供對應 CA 或憑證確為自簽。SSL: certificate subject name does not match target host name → 域名不匹配(可能訪問 IP 而非域名、或憑證綁定錯誤)。CURLOPT_CAINFO path not found → 路徑錯誤,建議用 __DIR__ 絕對路徑。curl_setopt_array($ch, [
CURLOPT_SSLCERT => __DIR__ . '/client.pem', // 客戶端憑證+私鑰
CURLOPT_SSLCERTTYPE => 'PEM',
CURLOPT_SSLKEY => __DIR__ . '/client.key', // 若私鑰分離
CURLOPT_SSLKEYTYPE => 'PEM',
CURLOPT_SSLKEYPASSWD => 'keypassword', // 私鑰密碼(如有)
]);
cacert.pem 並定期更新(Composer composer/ca-bundle 可自動維護)。curl_error($ch) 與 curl_getinfo($ch) 快速定位。