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

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

问题描述

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

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


  

PHP的警告:的fsockopen():SSL操作与code 1. OpenSSL的错误消息失败:
      错误:14090086:SSL例程:SSL3_GET_SERVER_CERTIFICATE:证书验证失败


code

 如果($计划生育=的fsockopen($主机,$端口,$的errno,$ errstr,20)){
    $这个 - >请求=POST.substr($这个 - > URL,strlen的($这个 - >主机))。 HTTP / 1.1'。$ CRLF
        .'Host:这 - $>主机$ CRLF。
        .'Content-长度:'$ CONTENT_LENGTH $ CRLF
        .'Connection:关闭'$ CRLF $ CRLF
        。$体;
    FWRITE($ FP,$这个 - >的要求);    而($行=与fgets($ FP)){
        如果($线!== FALSE){
            $这个 - 方式>响应= $行;
        }
    }    FCLOSE($ FP);
}

试过<​​/ H1>

 #光盘的/ etc / SSL /证书/
#wget的http://curl.haxx.se/ca/cacert.pem

的php.ini

  openssl.cafile =/etc/ssl/certs/cacert.pem

但脚本仍然无法正常工作

更新

此工作

 回声的file_get_contents(在/ etc / SSL /证书/ cacert.pem);

更新2

  $ contextOptions =阵列(
    'SSL'=&GT;阵列(
        verify_peer'=&GT;真实的,//你可以通过这个不断变化的假跳过所有的麻烦,但它是出于安全原因WAY酷。
        凭证档案错误'=&GT; /etc/ssl/certs/cacert.pem',
        //'CN_match'=&GT; 'example.com',//将此更改为您的证书公用名称(或只是注释此行是否没有必要)
        '密码'=&GT; 高!的SSLv2:SSLv3的,
        disable_com pression'=&GT;真正,
    )
);$语境= stream_context_create($ contextOptions);$计划生育=在stream_socket_client({$主机} {$}端口,$的errno,$ errstr,20,STREAM_CLIENT_CONNECT,$背景);

错误


  

PHP的警告:在stream_socket_client():SSL操作失败,code 1. OpenSSL的错误消息:
      错误:14090086:SSL例程:SSL3_GET_SERVER_CERTIFICATE:证书验证失败



解决方案

这是您下载的文件(的http://卷曲.haxx.se / CA / cacert.pem )是主要的受信任的证书当局的根证书捆绑。你说的远程主机具有自签名证书,所以它并没有使用受信任的证书。在 openssl.cafile 设置需要指向被用来签署远程主机上的SSL证书的CA证书。 PHP 5.6已经超过PHP的previous版本到现在验证默认同行证书和主机名提高(<一个href=\"http://php.net/manual/en/migration56.openssl.php\">http://php.net/manual/en/migration56.openssl.php)

您需要找到被签署的SSL证书并将其复制到该服务器在服务器上生成的CA证书。唯一的另一种选择是禁用验证同行,但打败了SSL安全。如果你想尝试禁用验证,试试这个数组与code从我的previous答案:

  $ contextOptions =阵列(
    'SSL'=&GT;阵列(
        verify_peer'=&GT;假,
        verify_peer_name'=&GT;假
    )
);

无论哪种方式,如果你使用自签名的证书,你需要添加CA证书被用来在远程主机的SSL证书登录到服务器上的可信商店,你是从连接或使用流上下文使用该证书为每个单独的请求。将它添加到受信任的证书是最简单的解决办法。就在远程主机的CA证书的内容添加到您下载的cacert.pem文件的末尾。

previous:

的fsockopen不支持流环境中,所以使用stream_socket_client来代替。它返回一个可与的fsockopen资源的所有命令中使用的资源。

这应该是替代你在你的问题有段下降:

 &LT; PHP$ contextOptions =阵列(
    'SSL'=&GT;阵列(
        verify_peer'=&GT;真实的,//你可以通过这个不断变化的假跳过所有的麻烦,但它是出于安全原因WAY酷。
        凭证档案错误'=&GT; /etc/ssl/certs/cacert.pem',
        CN_match'=&GT; 'example.com',//将此更改为您的证书公用名称(或只是注释此行是否没有必要)
        '密码'=&GT; 高!的SSLv2:SSLv3的,
        disable_com pression'=&GT;真正,
    )
);$语境= stream_context_create($ contextOptions);$计划生育=在stream_socket_client(TCP:// {$}主持人:{$}端口,$的errno,$ errstr,20,STREAM_CLIENT_CONNECT,$背景);如果(!$ FP){    回声$ errstr({$}错误号)LT; BR /&GT; \\ N的;}其他{    $这个 - &GT;请求=POST.substr($这个 - &GT; URL,strlen的($这个 - &GT;主机))。 HTTP / 1.1'。$ CRLF
        .'Host:这 - $&GT;主机$ CRLF。
        .'Content-长度:'$ CONTENT_LENGTH $ CRLF
        .'Connection:关闭'$ CRLF $ CRLF
        。$体;    FWRITE($ FP,$这个 - &GT;的要求);    而(!的feof($ FP)){
        $这个 - 方式&gt;响应=与fgets($ FP);
    }    FCLOSE($ FP);}

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 Warning: fsockopen(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

code

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

Have tried

# cd /etc/ssl/certs/
# wget http://curl.haxx.se/ca/cacert.pem

php.ini

openssl.cafile = "/etc/ssl/certs/cacert.pem"

But the script still fails to work

update

This works

echo file_get_contents("/etc/ssl/certs/cacert.pem");

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

error

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

解决方案

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)

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. The only other option is to disable verifying the peer, but that defeats the SSL security. If you DO want to try disabling verification, try this array with the code from my previous answer:

$contextOptions = array(
    'ssl' => array(
        'verify_peer' => false,
        'verify_peer_name' => false
    )
);

Either way, 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.

Previous:

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天全站免登陆