使用php通过https加载外部xml文件时出错:SSL3_GET_SERVER_CERTIFICATE


Error when loading external xml file with php via https : SSL3_GET_SERVER_CERTIFICATE

无法加载xml文件

这段代码工作得很好:

$url = 'http://www.w3schools.com/xml/note.xml';
$xml = simplexml_load_file($url);
print_r($xml);

但是这个

$url = 'https://www.boardgamegeek.com/xmlapi2/thing?id=105551';
$xml = simplexml_load_file($url);
print_r($xml);

是行不通的。我得到这个错误:

警告:simplexml_load_file(): SSL操作失败,代码1。OpenSSL错误消息:Error:14090086:SSL例程:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in/storage/content/59/113059/boardgamelevelup.com/public_html/index.php on line 19警告:simplexml_load_file(): failed to enable crypto in/storage/content/59/113059/boardgamelevelup.com/public_html/index.php on line 19警告:simplexml_load_file(https://www.boardgamegeek.com/xmlapi2/thing?id=105551):失败打开流:

操作失败/storage/content/59/113059/boardgamelevelup.com/public_html/index.php on line 19警告:simplexml_load_file(): I/O警告:加载/storage/content/59/113059/boardgamelevelup.com/public_html/index.php中的外部实体"https://www.boardgamegeek.com/xmlapi2/thing?id=105551"失败

来自boardgamegeek的xml文件适用于其他网站。我应该使用不同的php代码来加载xml文件吗?

简短的食谱答案:

  1. 下载https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt并将该文件放在服务器上。
  2. 添加
    $context = stream_context_create(array('ssl'=>array('verify_peer' => true,'cafile' => '/path/to/ca-bundle.crt')));libxml_set_streams_context(上下文)美元;

到你的脚本,这样它就会在simplexml_load_file()之前执行。
或者——而不是上面的代码——在php.ini中设置openssl.cafile=/path/to/ca-bundle.crt

非常简短的解释:
您的php版本使用openssl来处理https传输。Openssl尝试验证服务器是否真的是它所声称的服务器。它通过检查其证书是否受信任来做到这一点。X.509证书包含有关所有者的一些数据,并由发行者签名(其本身具有再次签名的证书,依此类推,直到所有者和发行者相同的证书->自签名/根证书)。如果在证书链中(至少)有一个证书openssl"说":"好的,我已经被指示信任这个证书",那么这个证书就被认为是"可信的"。该指令采用的形式为(或者可以采用的形式为)"这是一个包含您应该信任的证书的文件" (cafile).
当simplexml_load_file使用https/openssl-wrapper时,上面的代码告诉php的libxml-wrapper告诉openssl该文件在哪里。
openssl.cafile=/path/to/ca-bundle.crt把它设为默认值;除非另有指示,否则所有openssl操作都将使用该文件——包括libxml/simple_xml_loadfile。

ca-bundle。我链接到的crt来自一个项目,该项目"声称"提供mozilla firefox附带的提取根证书。关于"声明":我没有理由怀疑这确实是未篡改的根证书列表;但你永远不知道:你信任a)这个项目b) mozilla做得很好,只把值得信任的证书放在列表中....

更多说明请参见http://phpsecurity.readthedocs.org/en/latest/Transport-Layer-Security-%28HTTPS-SSL-and-TLS%29.html#php-streams

@VolkerK展示的作品和例子优秀而简单。虽然这种方法对我不起作用,但我更进一步,基本上暂时取消了安全性。

$context = stream_context_create(array('ssl'=>array(
    'verify_peer' => false, 
    "verify_peer_name"=>false
    )));
libxml_set_streams_context($context);
$sxml = simplexml_load_file($webhostedXMLfile);

是的,这是不好的做法,但有时您需要临时修复,而不是像这样的消息:

警告:simplexml_load_file(): SSL操作失败,代码1。OpenSSL错误信息:Error:14090086:SSL例程:SSL3_GET_SERVER_CERTIFICATE:证书验证失败/srv/www/resources/public_html/files/etc/file.php on line 150simplexml_load_file(): Failed to enable crypto in/srv/www/resources/public_html/files/etc/file.php on line 150

我希望它能帮助到别人。