[英]SSL error SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
升級到PHP 5.6后,嘗試通過fsockopen()
連接到服務器時出錯。
服務器(主機)上的證書是自簽名的
PHP警告:fsockopen():SSL操作失敗,代碼為1. OpenSSL錯誤消息:錯誤:14090086:SSL例程:SSL3_GET_SERVER_CERTIFICATE:證書驗證失敗
if($fp = fsockopen($host, $port, $errno, $errstr, 20)){
$this->request = 'POST '.substr($this->url, strlen($this->host)).' HTTP/1.1'.$crlf
.'Host: '.$this->host.$crlf
.'Content-Length: '.$content_length.$crlf
.'Connection: Close'.$crlf.$crlf
.$body;
fwrite($fp, $this->request);
while($line = fgets($fp)){
if($line !== false){
$this->response .= $line;
}
}
fclose($fp);
}
# cd /etc/ssl/certs/
# wget http://curl.haxx.se/ca/cacert.pem
php.ini中
openssl.cafile = "/etc/ssl/certs/cacert.pem"
但腳本仍無法正常工作
這有效
echo file_get_contents("/etc/ssl/certs/cacert.pem");
$contextOptions = array(
'ssl' => array(
'verify_peer' => true, // You could skip all of the trouble by changing this to false, but it's WAY uncool for security reasons.
'cafile' => '/etc/ssl/certs/cacert.pem',
//'CN_match' => 'example.com', // Change this to your certificates Common Name (or just comment this line out if not needed)
'ciphers' => 'HIGH:!SSLv2:!SSLv3',
'disable_compression' => true,
)
);
$context = stream_context_create($contextOptions);
$fp = stream_socket_client("{$host}:{$port}", $errno, $errstr, 20, STREAM_CLIENT_CONNECT, $context);
錯誤
PHP警告:stream_socket_client():SSL操作失敗,代碼為1. OpenSSL錯誤消息:錯誤:14090086:SSL例程:SSL3_GET_SERVER_CERTIFICATE:證書驗證失敗
您下載的文件( http://curl.haxx.se/ca/cacert.pem )是來自主要受信任證書頒發機構的一組根證書。 您說遠程主機具有自簽名SSL證書,因此它不使用可信證書。 openssl.cafile
設置需要指向用於在遠程主機上簽署SSL證書的CA證書。 PHP 5.6比以前的PHP版本有所改進,現在默認驗證對等證書和主機名( http://php.net/manual/en/migration56.openssl.php )
您需要找到在簽署SSL證書的服務器上生成的CA證書,並將其復制到此服務器。 唯一的另一種選擇是禁用驗證對等體,但這會破壞SSL安全性。 如果您想嘗試禁用驗證,請使用我之前的答案中的代碼嘗試此數組:
$contextOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false
)
);
無論哪種方式,如果您使用的是自簽名證書,則需要將用於簽署遠程主機SSL證書的CA證書添加到您要連接的服務器上的受信任存儲中,或者使用流上下文來使用每個請求的證書。 將其添加到可信證書是最簡單的解決方案。 只需將遠程主機CA證書的內容添加到您下載的cacert.pem文件的末尾即可。
以前:
fsockopen不支持流上下文,因此請改用stream_socket_client。 它返回一個資源,可以與fsockopen資源可以使用的所有命令一起使用。
這應該是您在問題中的代碼段的替代品:
<?php
$contextOptions = array(
'ssl' => array(
'verify_peer' => true, // You could skip all of the trouble by changing this to false, but it's WAY uncool for security reasons.
'cafile' => '/etc/ssl/certs/cacert.pem',
'CN_match' => 'example.com', // Change this to your certificates Common Name (or just comment this line out if not needed)
'ciphers' => 'HIGH:!SSLv2:!SSLv3',
'disable_compression' => true,
)
);
$context = stream_context_create($contextOptions);
$fp = stream_socket_client("tcp://{$host}:{$port}", $errno, $errstr, 20, STREAM_CLIENT_CONNECT, $context);
if (!$fp) {
echo "$errstr ({$errno})<br />\n";
}else{
$this->request = 'POST '.substr($this->url, strlen($this->host)).' HTTP/1.1'.$crlf
.'Host: '.$this->host.$crlf
.'Content-Length: '.$content_length.$crlf
.'Connection: Close'.$crlf.$crlf
.$body;
fwrite($fp, $this->request);
while (!feof($fp)) {
$this->response .= fgets($fp);
}
fclose($fp);
}
問題出在macOS Sierra的新PHP版本中
請加
stream_context_set_option($ctx, 'ssl', 'verify_peer', false);
我使用Docker在使用Ubuntu 16.04時遇到了類似的問題。 在我的情況下,這是Composer的問題,但錯誤消息(因此問題)是相同的。
由於極簡主義的面向Docker的基本映像,我缺少ca-certificates
包和簡單的apt-get install ca-certificates
幫助了我。
加
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
));
之前
mail->send()
並替換
require "mailer/class.phpmailer.php";
同
require "mailer/PHPMailerAutoload.php";
Firstable,確保您的防病毒軟件不會阻止SSL2。
因為我長時間無法解決問題,只有禁用防病毒幫助了我
你提到證書是自簽名的(由你)? 那你有兩個選擇:
cacert.pem
將不會執行任何操作,因為它是自簽名的) 以下是PHP中的SSL上下文選項列表: https : //secure.php.net/manual/en/context.ssl.php
設置allow_self_signed
如果導入您的證書到您的信任存儲,或者設置verify_peer
為false以跳過驗證。
我們信任特定證書的原因是因為我們信任其發行人 。 由於您的證書是自簽名的,因此簽名者(您)不受信任,因此任何客戶都不會信任該證書。 如果在簽署證書時創建了自己的CA,則可以將CA添加到信任庫。 如果您的證書不包含任何CA,那么您不能指望任何人連接到您的服務器。
在我的情況下,我在CentOS 7上,我的php安裝指向通過update-ca-trust
生成的證書。 符號鏈接是/etc/pki/tls/cert.pem
指向/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
。 這只是一個測試服務器,我希望我的自簽名證書能夠正常工作。 所以在我的情況下......
# My root ca-trust folder was here. I coped the .crt file to this location
# and renamed it to a .pem
/etc/pki/ca-trust/source/anchors/self-signed-cert.pem
# Then run this command and it will regenerate the certs for you and
# include your self signed cert file.
update-ca-trust
然后我的一些api調用開始工作,因為我的證書現在已被信任。 此外,如果您的ca-trust通過yum或其他內容進行更新,這將重建您的根證書並仍然包含您的自簽名證書。 運行man update-ca-trust
以獲取有關如何操作以及如何執行操作的更多信息。 :)
如果您使用的是macOS sierra,則會有PHP版本的更新。 您需要將Entrust.net證書頒發機構(2048)文件添加到PHP代碼中。 更多信息檢查接受的答案在這里使用PEM文件在PHP中推送通知
您是否嘗試過使用stream_context_set_option()
方法?
$context = stream_context_create();
$result = stream_context_set_option($context, 'ssl', 'local_cert', '/etc/ssl/certs/cacert.pem');
$fp = fsockopen($host, $port, $errno, $errstr, 20, $context);
此外,請嘗試pem文件的file_get_contents()
,以確保您有權訪問它,並確保主機名與證書匹配。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.