Я пытаюсь получить доступ к этой конкретной службе 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 в строке 2
Мы используем сервер Gentoo. Недавно мы обновили версию PHP 5.6. Это было после обновления, когда эта проблема появилась.
Когда я заменил службу REST, я обнаружил адрес, например https://www.google.com
; моя страница работает отлично.
В более ранней попытке я установил “verify_peer”=>false
и передал это как аргумент file_get_contents, как описано здесь: file_get_contents, игнорируя verify_peer => false? Но, как заметил писатель; это не имело никакого значения.
Я спросил одного из наших администраторов серверов, есть ли эти строки в нашем файле php.ini:
Он сказал мне, что, поскольку мы на Gentoo, openssl скомпилируется, когда мы создаем; и он не установлен в файле php.ini.
Я также подтвердил, что allow_url_fopen
работает. В связи с особым характером этой проблемы; Я не нахожу много информации для помощи. Кто-нибудь из вас сталкивался с чем-то подобным? Благодарю.
Это была чрезвычайно полезная ссылка, чтобы найти:
http://php.net/manual/en/migration56.openssl.php
Официальный документ, описывающий изменения, сделанные для открытия 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; ?>
Вы не должны просто отключать проверку. Скорее, вы должны скачать комплект сертификатов, возможно, это сделает скручивание ?
Затем вам просто нужно разместить его на своем веб-сервере, предоставляя пользователю, который запускает 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));
Надеемся, что корневой сертификат сайта, к которому вы пытаетесь получить доступ, находится в комплекте с завитки. Если это не так, это все равно не будет работать, пока вы не получите корневой сертификат сайта и не поместите его в файл сертификата.
Я исправил это, убедившись, что этот OpenSSL был установлен на моей машине, а затем добавив это в мой php.ini:
openssl.cafile=/usr/local/etc/openssl/cert.pem
Если ваша версия php равна 5. Затем попробуйте это fix.Install curl, набрав следующие команды в терминале.
sudo apt-get install php5-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.
В основном вы должны установить переменную среды SSL_CERT_FILE на путь файла PEM сертификата ssl, загруженного по следующей ссылке: http://curl.haxx.se/ca/cacert.pem .
Мне потребовалось много времени, чтобы понять это.
Просто хотел добавить к этому, так как я столкнулся с одной и той же проблемой, и ничто из того, что я мог найти в любом месте, не будет работать (например, загрузка файла cacert.pem, установка cafile в php.ini и т. Д.)
Если вы используете NGINX, а ваш сертификат SSL поставляется с «промежуточным сертификатом», вам необходимо объединить промежуточный файл сертификата с вашим основным файлом «mydomain.com.crt», и он должен работать. У Apache есть параметр, специфичный для промежуточных сертификатов, но NGINX не так, он должен находиться в том же файле, что и ваш обычный сертификат.
Имел ту же самую ssl-проблему на моей машине разработчика (php 7, xampp на окнах) с самоподписанным сертификатом, пытающимся открыть файл « https: // localhost / …». Очевидно, что root-certificate-assembly (cacert.pem) не работает. Я просто скопировал код из файла apache server.crt в загруженном файле cacert.pem и выполнил запись openssl.cafile = path / to / cacert.pem в php.ini
Причина этой ошибки заключается в том, что PHP не имеет списка доверенных центров сертификации.
PHP 5.6 и более поздние версии попытаются загрузить ЦС, которым доверяет система автоматически. Проблемы с этим могут быть исправлены. См. http://php.net/manual/en/migration56.openssl.php для получения дополнительной информации.
PHP 5.5 и более ранние версии очень трудно настроить правильно, так как вам вручную нужно указать пакет CA в каждом контексте запроса, что вы не хотите посыпать своим кодом. Поэтому я решил для своего кода, что для версий PHP <5.6 проверка SSL просто отключается:
$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); }
Что касается ошибок, подобных
[11-May-2017 19:19:13 America / Chicago] PHP Warning: file_get_contents (): операция SSL завершилась неудачно с кодом 1. OpenSSL Сообщения об ошибках: ошибка: 14090086: Подпрограммы SSL: ssl3_get_server_certificate: проверка сертификата не выполнена
Вы проверили разрешения сертификатов и каталогов, на которые ссылается 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
Проблема была исправлена, по крайней мере, для меня.
Имела ту же ошибку с PHP 7 на XAMPP и OSX.
Вышеупомянутый ответ в https://stackoverflow.com/ хорош, но он не полностью решил проблему для меня. Я должен был предоставить полную цепочку сертификатов, чтобы файл file_get_contents () снова работал. Вот как я это сделал:
Получить корневой / промежуточный сертификат
Прежде всего мне нужно было выяснить, что такое корень и промежуточный сертификат.
Самый удобный способ – это, возможно, онлайн-сертификат, например, 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 ищет файлы сертификатов. И есть этот параметр, который скажет 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 () снова работает. Без CURL и, надеюсь, без недостатков безопасности.