file_get_contents(): SSL 操作失败,代码为 1,无法启用加密

2022-08-30 06:11:30

我一直在尝试从我在服务器上创建的PHP页面访问这个特定的REST服务。我把问题缩小到这两条线。所以我的PHP页面看起来像这样:

<?php
$response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json");

echo $response; ?>

页面在第 2 行死机,并出现以下错误:

  • 警告:file_get_contents(): SSL 操作失败,代码为 1。OpenSSL 错误消息:错误:14090086:SSL 例程:SSL3_GET_SERVER_CERTIFICATE:证书验证在 ...第 2 行的 php
    • 警告:file_get_contents(): 无法在 ...第 2 行的 php
    • 警告:file_get_contents(): 无法打开流: 操作失败 ...第 2 行的 phphttps://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json

我们使用的是Gentoo服务器。我们最近升级到 PHP 版本 5.6。升级后才出现此问题。

我发现当我用这样的地址替换REST服务时;我的页面工作正常。https://www.google.com

在之前的一次尝试中,我设置了 ,并将其作为参数传递给file_get_contents,如下所述:file_get_contents忽略 verify_peer=>false?但正如作者指出的那样;这没有任何区别。“verify_peer”=>false

我问过我们的一位服务器管理员,我们的php.ini文件中是否存在这些行:

  • 扩展名 = php_openssl.dll
  • allow_url_fopen = 开

他告诉我,由于我们在Gentoo上,所以opensl在我们构建时是编译的。并且它没有在php.ini文件中设置。

我还确认这是有效的。由于这个问题的特殊性;我没有找到很多帮助的信息。你们有没有遇到过这样的事情?谢谢。allow_url_fopen


答案 1

这是一个非常有帮助的链接,可以找到:

http://php.net/manual/en/migration56.openssl.php

一个官方文档描述了在 PHP 5.6 中打开 ssl 所做的更改 从这里我了解到另一个参数,我应该设置为 false:“verify_peer_name”=>false

注意:这具有非常重要的安全隐患。禁用验证可能允许 MITM 攻击者使用无效证书来窃听请求。虽然在本地开发中执行此操作可能很有用,但在生产中应使用其他方法。

所以我的工作代码看起来像这样:

<?php
$arrContextOptions=array(
    "ssl"=>array(
        "verify_peer"=>false,
        "verify_peer_name"=>false,
    ),
);  

$response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json", false, stream_context_create($arrContextOptions));

echo $response; ?>

答案 2

您不应该只是关闭验证。相反,您应该下载证书捆绑包,也许 curl 捆绑包可以?

然后,您只需要将其放在Web服务器上,即可授予运行php的用户读取该文件的权限。那么这段代码应该适用于你:

$arrContextOptions= [
    'ssl' => [
        'cafile' => '/path/to/bundle/cacert.pem',
        'verify_peer'=> true,
        'verify_peer_name'=> true,
    ],
];

$response = file_get_contents(
    'https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json',
    false,
    stream_context_create($arrContextOptions)
);

希望您尝试访问的站点的根证书位于 curl 包中。如果不是,则在获取站点的根证书并将其放入证书文件之前,这仍然不起作用。


推荐