file_get_contents(): операция SSL не выполнена с кодом 1, не удалось включить шифрование
Я пытаюсь получить доступ к этой конкретной службе REST с PHP-страницы Ive, созданной на нашем сервере. Я сузил проблему до этих двух строк. Итак, моя страница 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 = > false? как отметил писатель; это не имело никакого значения.
Ive спросил одного из наших администраторов серверов, существуют ли эти строки в нашем файле php.ini:
- расширение = php_openssl.dll
- allow_url_fopen = On
Он сказал мне, что с тех пор, как они были на Gentoo, openssl скомпилируется, когда мы создаем; и его не задано в файле php.ini.
Я также подтвердил, что работает allow_url_fopen
. В связи с особым характером этой проблемы; Я не нахожу много информации для помощи. Кто-нибудь из вас сталкивался с чем-то подобным? Благодарю.
Ответы
Ответ 1
Это была чрезвычайно полезная ссылка для поиска:
http://php.net/manual/en/migration56.openssl.php
Официальный документ, описывающий изменения, внесенные в open ssl в PHP 5.6
Отсюда я узнал еще об одном параметре, который я должен был установить в 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?
Затем вам просто нужно поместить его на свой веб-сервер, предоставив пользователю разрешение на чтение 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. Если это не так, это все равно не будет работать, пока вы не получите корневой сертификат сайта и не поместите его в файл сертификата.
Ответ 3
Я исправил это, убедившись, что этот OpenSSL был установлен на моем компьютере, а затем добавив его в мой php.ini:
openssl.cafile=/usr/local/etc/openssl/cert.pem
Ответ 4
Вы можете обойти эту проблему, написав пользовательскую функцию, которая использует 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.
Ответ 5
Если ваша версия PHP равна 5, попробуйте установить cURL, введя в терминал следующую команду:
sudo apt-get install php5-curl
Ответ 6
В основном вы должны установить переменную среды SSL_CERT_FILE на путь файла PEM сертификата ssl, загруженного по следующей ссылке: http://curl.haxx.se/ca/cacert.pem.
Мне потребовалось много времени, чтобы понять это.
Ответ 7
следующие шаги будут устранять эту проблему,
- Загрузите сертификат CA по этой ссылке: https://curl.haxx.se/ca/cacert.pem
- Найти и открыть php.ini
- Найдите
curl.cainfo
и вставьте абсолютный путь, на который вы загрузили сертификат. curl.cainfo ="C:\wamp\htdocs\cert\cacert.pem"
- Перезапустите WAMP/XAMPP (сервер Apache).
- Оно работает!
надеюсь, это поможет !!
Ответ 8
Работая на меня, я использую PHP 5.6. Расширение openssl должно быть включено и при вызове карты Google API api verify_peer сделать false
Ниже код работает для меня.
<?php
$arrContextOptions=array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
),
);
$url = "https://maps.googleapis.com/maps/api/geocode/json?latlng="
. $latitude
. ","
. $longitude
. "&sensor=false&key="
. Yii::$app->params['GOOGLE_API_KEY'];
$data = file_get_contents($url, false, stream_context_create($arrContextOptions));
echo $data;
?>
Ответ 9
Просто хотел добавить к этому, так как я столкнулся с одной и той же проблемой и ничего не смог найти в любом месте (например, загрузка файла cacert.pem, установка cafile в php.ini и т.д.)
Если вы используете NGINX, а ваш сертификат SSL поставляется с "промежуточным сертификатом", вам необходимо объединить промежуточный файл сертификата с вашим основным файлом "mydomain.com.crt", и он должен работать. У Apache есть параметр, специфичный для промежуточных сертификатов, но NGINX не так, он должен находиться в том же файле, что и ваш обычный сертификат.
Ответ 10
Причиной этой ошибки является то, что PHP не имеет списка доверенных сертификатов.
PHP 5.6 и более поздние версии попытайтесь загрузить CA, которым доверяет система автоматически. Проблемы с этим могут быть исправлены. Подробнее см. 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
Имела ту же ошибку с PHP 7 на XAMPP и OSX.
Вышеупомянутый ответ в fooobar.com/questions/63590/... хорош, но он не полностью решил проблему для меня. Я должен был предоставить полную цепочку сертификатов, чтобы файл file_get_contents() снова работал. Вот как я это сделал:
Получить сертификат root/промежуточный
Прежде всего мне нужно было выяснить, что такое корень и промежуточный сертификат.
Самый удобный способ - это, возможно, онлайн-сертификат, например 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 и, надеюсь, без недостатков безопасности.
Ответ 12
Имела ту же самую ssl-проблему на моей машине разработчика (php 7, xampp на окнах) с самоподписанным сертификатом, пытающимся скрыть " https://localhost/..." - файл. Очевидно, что root-certificate-assembly (cacert.pem) не работает.
Я просто скопировал вручную код из файла apache server.crt файла в загруженном файле cacert.pem и выполнил запись openssl.cafile = path/to/cacert.pem в php.ini
Ответ 13
После того, как я стал жертвой этой проблемы в CentOS после обновления php до php5.6, я нашел решение, которое помогло мне.
Получите правильный каталог для ваших сертификатов, который будет размещен по умолчанию с этим
php -r 'print_r(openssl_get_cert_locations()["default_cert_file"]);'
Затем используйте это, чтобы получить сертификат и поместить его в местоположение по умолчанию, найденное из кода выше
wget http://curl.haxx.se/ca/cacert.pem -O <default location>
Ответ 14
Относительно ошибок, подобных
[11-May-2017 19:19:13 Америка/Чикаго] Предупреждение PHP: 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
Проблема была исправлена, по крайней мере, для меня в любом случае.
Ответ 15
Еще одна попытка - переустановить ca-certificates
как описано здесь.
# yum reinstall ca-certificates
...
# update-ca-trust force-enable
# update-ca-trust extract
И еще одна вещь, которую нужно попробовать, это явно разрешить один сертификат соответствующего сайта, как описано здесь (особенно, если один сайт является вашим собственным сервером, и у вас уже есть доступ к .pem).
# cp /your/site.pem /etc/pki/ca-trust/source/anchors/
# update-ca-trust extract
Я столкнулся с этой точной ошибкой SO после обновления до PHP 5.6 на CentOS 6, пытаясь получить доступ к самому серверу, который имеет сертификат cheapsslsecurity, который, возможно, его нужно было обновить, но вместо этого я установил сертификат letsencrypt, и с этими двумя шагами выше он сделал трюк. Я не знаю, почему был необходим второй шаг.
Полезные команды
Посмотреть версию openssl:
# openssl version
OpenSSL 1.0.1e-fips 11 Feb 2013
Посмотреть текущие настройки PHP cli ssl:
# php -i | grep ssl
openssl
Openssl default config => /etc/pki/tls/openssl.cnf
openssl.cafile => no value => no value
openssl.capath => no value => no value
Ответ 16
У меня была такая же проблема для другой безопасной страницы при использовании wget
или file_get_contents
. Многие исследования (включая некоторые ответы на этот вопрос) привели к простому решению - установке Curl и PHP-Curl. Если я правильно понял, Curl имеет корневой CA для Comodo, который разрешил проблему
Установите Curl и PHP-Curl addon, затем перезапустите Apache
sudo apt-get install curl
sudo apt-get install php-curl
sudo /etc/init.d/apache2 reload
Теперь все работает.
Ответ 17
В моем случае эта функция работала правильно, пока вы не установили антивирус AVG, временно отключив AVG, все возвращается к нормальной работе.