file_get_contents (): операция SSL не удалась с кодом 1. И многое другое

Я пытался получить доступ к этой конкретной службе REST со страницы PHP, которую я создал на нашем сервере. Я сузил проблему до этих двух строк. Итак, моя страница 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: сбой проверки сертификата в
    … PHP в строке 2

    • Предупреждение: file_get_contents (): не удалось включить шифрование в … php on
      строка 2
    • Предупреждение:
      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):
      не удалось открыть поток: операция не удалась в … php в строке 2

Мы используем сервер Gentoo. Недавно мы обновились до версии PHP 5.6. Именно после обновления появилась эта проблема.

Я нашел, когда я заменяю REST-сервис с адресом вроде https://www.google.com; моя страница работает просто отлично.

В более ранней попытке я установил “verify_peer”=>falseи передал это в качестве аргумента file_get_contents, как описано здесь: file_get_contents игнорируя verify_peer =>ложный? Но, как заметил писатель; это не имело никакого значения.

Я спросил одного из наших администраторов сервера, существуют ли эти строки в нашем файле php.ini:

  • расширение = php_openssl.dll
  • allow_url_fopen = On

Он сказал мне, что поскольку мы находимся на Gentoo, openssl компилируется при сборке; и это не установлено в файле php.ini.

Я также подтвердил, что allow_url_fopen работает. В связи со спецификой этой проблемы; Я не нахожу много информации для помощи. Кто-нибудь из вас сталкивался с чем-то подобным? Благодарю.

141

Решение

Это была чрезвычайно полезная ссылка для поиска:

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

Официальный документ, описывающий изменения, внесенные в open ssl в PHP 5.6
Отсюда я узнал еще об одном параметре, который я должен был установить в false: «verify_peer_name» => false

Итак, мой рабочий код выглядит так:

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

Другие решения

Вы не должны просто отключить проверку. Скорее вы должны загрузить пакет сертификатов, возможно, локон расслоение подойдет?

Затем вам просто нужно поместить его на ваш веб-сервер, предоставив пользователю, который запускает php, разрешение на чтение файла. Тогда этот код должен работать для вас:

$arrContextOptions=array(
"ssl"=>array(
"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. Если это не так, это все равно не будет работать, пока вы не получите корневой сертификат сайта и не поместите его в файл сертификата.

128

Я исправил это, убедившись, что OpenSSL был установлен на моей машине, а затем добавил это в мой php.ini:

openssl.cafile=/usr/local/etc/openssl/cert.pem
26

Вы можете обойти эту проблему, написав пользовательскую функцию, которая использует curl, например:

function file_get_contents_curl( $url ) {

$ch = curl_init();

curl_setopt( $ch, CURLOPT_AUTOREFERER, TRUE );
curl_setopt( $ch, CURLOPT_HEADER, 0 );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, TRUE );

$data = curl_exec( $ch );
curl_close( $ch );

return $data;

}

Тогда просто используйте file_get_contents_curl вместо file_get_contents всякий раз, когда вы вызываете URL, который начинается с https.

12

Если у вас версия PHP 5, попробуйте установить cURL, набрав в терминале следующую команду:

sudo apt-get install php5-curl
10

По сути, вы должны установить переменную среды SSL_CERT_FILE равной пути файла PEM ssl-сертификата, загруженного по следующей ссылке: http://curl.haxx.se/ca/cacert.pem.

Мне понадобилось много времени, чтобы понять это.

7

следующие шаги помогут решить эту проблему,

  1. Загрузите сертификат CA по этой ссылке: https://curl.haxx.se/ca/cacert.pem
  2. Найдите и откройте php.ini
  3. Ищу curl.cainfo и вставьте абсолютный путь где у вас есть скачать сертификат. curl.cainfo ="C:\wamp\htdocs\cert\cacert.pem"
  4. Перезапустите WAMP / XAMPP (сервер Apache).
  5. Оно работает!

надеюсь, это поможет !!

6

Просто хотел добавить к этому, так как столкнулся с той же проблемой, и ничего, что я нигде не мог найти, работало бы (например, загрузка файла cacert.pem, настройка cafile в php.ini и т. Д.)

Если вы используете NGINX и ваш SSL-сертификат поставляется с «промежуточным сертификатом», вам нужно объединить промежуточный файл сертификата с вашим основным файлом «mydomain.com.crt», и он должен работать. Apache имеет настройку, специфичную для промежуточных сертификатов, но NGINX нет, поэтому он должен находиться в том же файле, что и ваш обычный сертификат.

4
По вопросам рекламы [email protected]