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 на строка 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 on line 2
Мы используем сервер Gentoo. Мы недавно обновили PHP до версии 5.6. Эта проблема возникла уже после обновления.
Я нашел, когда заменил службу REST на адрес типа https://www.google.com
; Моя страница работает просто отлично.
В более ранняя попытка я установил “verify_peer”=>false
, и передал это в качестве аргумента file_get_contents, как описано здесь: file_get_contents игнорируя verify_peer= > false?Но, как заметил писатель, это не имело никакого значения.
Я спросил одного из наших администраторов сервера, есть ли эти строки в нашем php.ini файл существует:
- extension=php_openssl.dll
- allow_url_fopen = On
Я также подтвердил, что allow_url_fopen
работает. Из-за специализированного характера этой проблемы, я не нахожу много информации для помощи. Кто-нибудь из вас сталкивался с чем-то подобным? Спасибо.
14 ответов:
Это была чрезвычайно полезная ссылка, чтобы найти:
Http://php.net/manual/en/migration56.openssl.php
Официальный документ, описывающий изменения, внесенные для открытия ssl в PHP 5.6 Отсюда я узнал еще один параметр, который я должен иметь значение 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; ?>
Вы не должны просто отключать проверку. Скорее вам следует загрузить пакет сертификатов, возможно, подойдет пакетcurl ?
Тогда вам просто нужно поместить его на свой веб-сервер, предоставив пользователю, который запускает 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. Если это не так, это все равно не будет работать, пока вы не получите корневой сертификат сайта и не поставите это в ваш файл сертификата.
Я исправил это, убедившись, что OpenSSL был установлен на моей машине, а затем добавил Это в мой php.ini:
openssl.cafile=/usr/local/etc/openssl/cert.pem
Вы можете обойти эту проблему, написав пользовательскую функцию, которая использует 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.
Если ваша версия PHP 5, попробуйте установить cURL, введя следующую команду в терминале:
sudo apt-get install php5-curl
В основном вам нужно установить переменную среды SSL_CERT_FILE в путь PEM-файла ssl-сертификата, загруженного по следующей ссылке: http://curl.haxx.se/ca/cacert.pem .
Мне потребовалось много времени, чтобы понять это.
Следующие ниже шаги устранят эту проблему,
- загрузите сертификат CA по этой ссылке: https://curl.haxx.se/ca/cacert.pem
- Найдите и откройте php.ini
- Найдите
curl.cainfo
и вставьте абсолютный путь, где вы загрузили сертификат.curl.cainfo ="C:\wamp\htdocs\cert\cacert.pem"
- перезагрузите WAMP/XAMPP (сервер apache).
- это работает!
Надеюсь, это поможет !!
Просто хотел добавить к этому, так как я столкнулся с той же проблемой, и ничего я не мог найти нигде не будет работать (например, загрузка cacert.PEM файл, установка cafile в php.Ини и т. д.)
Если вы используете NGINX и ваш SSL-сертификат поставляется с "промежуточным сертификатом", вам нужно объединить промежуточный файл cert с вашим основным файлом "mydomain.com.crt", и он должен работать. Apache имеет настройку, специфичную для промежуточных сертификатов, но NGINX этого не делает, поэтому он должен находиться в том же файле, что и ваш обычный сертификат.
Причина этой ошибки заключается в том, что PHP не имеет списка доверенных центров сертификации.
PHP 5.6 и более поздние версии пытаются автоматически загрузить CAs, которым доверяет система. Проблемы с этим можно исправить. См. http://php.net/manual/en/migration56.openssl.php для получения дополнительной информации.
PHP 5.5 и более ранние версии действительно трудно правильно настроить, так как вы вручную должны указать пакет CA в каждом контексте запроса, вещь, которую вы не хотите разбрасывать вокруг вашего код. Поэтому я решил для своего кода, что для PHP версий
$req = new HTTP_Request2($url); if (version_compare(PHP_VERSION, '5.6.0', '<')) { //correct ssl validation on php 5.5 is a pain, so disable $req->setConfig('ssl_verify_host', false); $req->setConfig('ssl_verify_peer', false); }
Была такая же проблема ssl на моей машине разработчика (php 7, xampp на windows) с самозаверяющим сертификатом, пытающимся открыть "https://localhost/..."-файл. Очевидно, что корневой сертификат-сборка (cacert.pem) не сработало. Я просто скопировал вручную код с сервера apache.crt-файл в скачанном cacert.Пем и сделал openssl.cafile=путь/к / cacert.запись pem в php.ini
Была такая же ошибка с PHP 7 на XAMPP и OSX.
Вышеупомянутый ответ в https://stackoverflow.com/ это хорошо, но это не полностью решило проблему для меня. Мне пришлось предоставить полную цепочку сертификатов, чтобы заставить file_get_contents () снова работать. Вот как я это сделал:
Получить корневой / промежуточный сертификат
Прежде всего я должен был выяснить, что такое корневойи промежуточный сертификат.
Самый удобный способ-это, возможно, онлайн-cert-инструмент, такой как ssl-shopper
Там я нашел три сертификата, один серверный сертификат и два цепных сертификата (один-корневой, другой-явно промежуточный). Все, что мне нужно сделать, это просто поискать их обоих в интернете. В моем случае это корень:Thawte DV SSL SHA256 CA
И это приводит к его url thawte.com поэтому я просто поместил этот сертификат в текстовый файл и сделал то же самое. для промежуточного звена. Сделано.
Получить сертификат хоста
Следующее, что я должен был сделать, это загрузить мой серверный сертификат. В Linux или OS X это можно сделать с помощью openssl:
openssl s_client -showcerts -connect whatsyoururl.de:443 </dev/null 2>/dev/null|openssl x509 -outform PEM > /tmp/whatsyoururl.de.cert
Теперь соберите их всех вместе
Теперь просто объедините их все в один файл. (Может быть, лучше просто поместить их в одну папку, я просто объединил их в один файл). Вы можете сделать это так:cat /tmp/thawteRoot.crt > /tmp/chain.crt cat /tmp/thawteIntermediate.crt >> /tmp/chain.crt cat /tmp/tmp/whatsyoururl.de.cert >> /tmp/chain.crt
Скажите PHP, где найти цепочку
Есть такое удобная функция openssl_get_cert_locations (), которая подскажет вам, где PHP ищет файлы cert. И есть этот параметр, который подскажет file_get_contents (), где искать файлы cert. Может быть, сработают оба способа. Я предпочитал путь параметров. (По сравнению с решением, упомянутым выше).
Итак, теперь это мой PHP-код
$arrContextOptions=array( "ssl"=>array( "cafile" => "/Applications/XAMPP/xamppfiles/share/openssl/certs/chain.pem", "verify_peer"=> true, "verify_peer_name"=> true, ), ); $response = file_get_contents($myHttpsURL, 0, stream_context_create($arrContextOptions));
Вот и все. file_get_contents() снова работает. Без завитков и, надеюсь, без изъянов в системе безопасности.
После того, как я стал жертвой этой проблемы на centOS после обновления php до php5. 6, я нашел решение, которое сработало для меня.
Получите правильный каталог для размещения сертификатов по умолчанию с помощью этого
php -r 'print_r(openssl_get_cert_locations());' | grep '\[default_cert_file\]' | awk '{print $3}'
Затем используйте это, чтобы получить сертификат и поместить его в расположение по умолчанию, найденное из кода выше
wget http://curl.haxx.se/ca/cacert.pem -O <default location>
Относительно ошибок, подобных
[11-May-2017 19: 19: 13 America / Chicago] PHP Warning: file_get_contents (): сбой SSL-операции с кодом 1. Сообщения об ошибках OpenSSL: ошибка: 14090086: SSL-процедуры: ssl3_get_server_certificate: ошибка проверки сертификата
Вы проверили разрешения cert и каталогов, на которые ссылается openssl?
Вы можете сделать это
var_dump(openssl_get_cert_locations());
Чтобы получить нечто подобное этому
array(8) { ["default_cert_file"]=> string(21) "/usr/lib/ssl/cert.pem" ["default_cert_file_env"]=> string(13) "SSL_CERT_FILE" ["default_cert_dir"]=> string(18) "/usr/lib/ssl/certs" ["default_cert_dir_env"]=> string(12) "SSL_CERT_DIR" ["default_private_dir"]=> string(20) "/usr/lib/ssl/private" ["default_default_cert_area"]=> string(12) "/usr/lib/ssl" ["ini_cafile"]=> string(0) "" ["ini_capath"]=> string(0) "" }
Этот вопрос расстроил меня на некоторое время, пока я не начал я понял, что у моей папки" certs " было 700 разрешений, тогда как она должна была иметь 755 разрешений. Помните, что это папка не для ключей, а для сертификатов. Я рекомендую прочитать эту эту ссылку на разрешения ssl.
Однажды я это сделал
chmod 755 certs
Проблема была решена, в любом случае, по крайней мере для меня.
У меня была такая же проблема для другой защищенной страницы при использовании
wget
илиfile_get_contents
. Множество исследований (включая некоторые ответы на этот вопрос) привели к простому решению-установке Curl и PHP-Curl-если я правильно понял, Curl имеет корневой CA для Comodo, который решил проблемуУстановите Curl и PHP-curl аддон, затем перезагрузите Apache
sudo apt-get install curl sudo apt-get install php-curl sudo /etc/init.d/apache2 reload
Все теперь работают.