【问题标题】:Error when loading external xml file with php via https : SSL3_GET_SERVER_CERTIFICATE通过 https 使用 php 加载外部 xml 文件时出错:SSL3_GET_SERVER_CERTIFICATE
【发布时间】:2015-12-13 19:50:46
【问题描述】:

我无法加载要加载的 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 错误消息:错误:14090086:SSL 例程:SSL3_GET_SERVER_CERTIFICATE:/storage/content/59/113059/boardgamelevelup.com/public_html/index 中的证书验证失败。第 19 行的 php 警告:simplexml_load_file():无法在第 19 行的 /storage/content/59/113059/boardgamelevelup.com/public_html/index.php 中启用加密 警告:simplexml_load_file(https://www.boardgamegeek.com/xmlapi2/thing?id=105551):无法打开流:第 19 行 /storage/content/59/113059/boardgamelevelup.com/public_html/index.php 中的操作失败警告:simplexml_load_file():I/O 警告:无法在 /storage/content 中加载外部实体“https://www.boardgamegeek.com/xmlapi2/thing?id=105551” /59/113059/boardgamelevelup.com/public_html/index.php 第 19 行

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

【问题讨论】:

标签: php xml


【解决方案1】:

简短的食谱答案:

  1. 下载https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt 并将该文件放在您的服务器上。
  2. 添加

    $context = stream_context_create(array('ssl'=>array(
        'verify_peer' => 真,
        'cafile' => '/path/to/ca-bundle.crt'
    )));
    libxml_set_streams_context($context);

到您的脚本,以便它在 simplexml_load_file() 之前执行。
或者 - 代替上面的代码 - 在你的 php.ini 中设置 openssl.cafile=/path/to/ca-bundle.crt

非常简短的解释:
您的 php 版本使用 openssl 来处理 https 传输。 openssl 尝试验证服务器是否真的是它声称的那个人。它通过检查其证书是否可信来做到这一点。 X.509 证书包含有关所有者的一些数据并由颁发者签名(本身具有再次签名的证书,依此类推,直到所有者和颁发者相同的证书 -> 自签名/根证书)。如果在该证书链中有(至少)一个证书,openssl “说”:“好的,我已指示信任这个证书”,则该证书被认为是“受信任的”。该指令采用(或可以采用)“这是一个包含您应该信任的证书的文件”(cafile)的形式。
上面的代码告诉 php 的 libxml-wrapper 在 simplexml_load_file 使用 https/openssl-wrapper 时告诉 openssl 那个 cafile 在哪里。
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!那行得通。也感谢您的解释,这有助于理解问题。
  • 为像我这样的谷歌用户添加了几个:php -i | grep 'Configuration File' 找到 php.ini wget -P /path/to/cert/ https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt 将证书保存到文件夹中。然后重启apachesystemctl restart httpd
【解决方案2】:

@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 错误消息:错误:14090086:SSL 例程:SSL3_GET_SERVER_CERTIFICATE:证书验证失败 /srv/www/resources/public_html/files/etc/file.php 第 150 行警告: simplexml_load_file():无法启用加密 /srv/www/resources/public_html/files/etc/file.php 第 150 行

我希望它可以帮助别人。

【讨论】:

  • 非常感谢。它绝对救了我
  • 在我的情况下,仅使用 'verify_peer' 设置为 false 就足够了。
猜你喜欢
  • 2014-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-22
  • 2012-07-16
  • 1970-01-01
  • 2012-06-17
相关资源
最近更新 更多