SSL 错误 SSL3_GET_SERVER_CERTIFICATE:证书验证失败 [英] SSL error SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

查看:86
本文介绍了SSL 错误 SSL3_GET_SERVER_CERTIFICATE:证书验证失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

升级到 PHP 5.6 后,当我尝试通过 fsockopen() 连接到服务器时出现错误..

After upgrading to PHP 5.6 I get an error when trying to connect to a server via fsockopen()..

服务器(主机)上的证书是自签名的

The certificate on the server (host) is self-signed

PHP 警告:fsockopen():SSL 操作失败,代码为 1.OpenSSL 错误消息:错误:14090086:SSL 例程:SSL3_GET_SERVER_CERTIFICATE:证书验证失败

PHP Warning: fsockopen(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

代码

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");

更新 2

$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:证书验证失败

PHP Warning: stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

推荐答案

您下载的文件 (http://curl.haxx.se/ca/cacert.pem) 是来自主要受信任证书颁发机构的一组根证书.你说远程主机有一个自签名的 SSL 证书,所以它没有使用受信任的证书.openssl.cafile 设置需要指向用于签署远程主机上的 SSL 证书的 CA 证书.PHP 5.6 已比以前的 PHP 版本改进,现在默认验证对等证书和主机名 (http://php.net/manual/en/migration56.openssl.php)

The file that you downloaded (http://curl.haxx.se/ca/cacert.pem) is a bundle of the root certificates from the major trusted certificate authorities. You said that the remote host has a self-signed SSL certificate, so it didn't use a trusted certificate. The openssl.cafile setting needs to point to the CA certificate that was used to sign the SSL certificate on the remote host. PHP 5.6 has been improved over previous versions of PHP to now verify peer certificates and host names by default (http://php.net/manual/en/migration56.openssl.php)

您需要找到在签署 SSL 证书的服务器上生成的 CA 证书并将其复制到此服务器.如果您使用的是自签名证书,则需要将用于对远程主机的 SSL 证书进行签名的 CA 证书添加到您正在连接的服务器上的受信任存储中,或者使用流上下文来使用该证书每个单独的请求.将其添加到受信任证书是最简单的解决方案.只需将远程主机的 CA 证书的内容添加到您下载的 cacert.pem 文件的末尾即可.

You'll need to locate the CA certificate that was generated on the server that signed the SSL certificate and copy it to this server. If you're using self-signed certificates, you'll need to add the CA cert that was used to sign the remote host's SSL certificate to the trusted store on the server you're connecting from OR use stream contexts to use that certificate for each individual request. Adding it to the trusted certificates is the simplest solution. Just add the contents of the remote host's CA cert to the end of the cacert.pem file you downloaded.

上一个:

fsockopen 不支持流上下文,因此请改用 stream_socket_client.它返回一个可以与 fsockopen 资源可以使用的所有命令一起使用的资源.

fsockopen doesn't support stream contexts, so use stream_socket_client instead. It returns a resource that can be used with all the commands that fsockopen resources can.

这应该是您问题中的片段的替代品:

This should be a drop in replacement for the snippet you have in your question:

<?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);

}

这篇关于SSL 错误 SSL3_GET_SERVER_CERTIFICATE:证书验证失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆