Как заставить file_get_contents () работать с HTTPS?


106

Я работаю над настройкой обработки кредитных карт, и мне нужно использовать обходной путь для CURL. Следующий код работал нормально, когда я использовал тестовый сервер (который не вызывал URL-адрес SSL), но теперь, когда я тестирую его на рабочем сервере с HTTPS, он выдает сообщение об ошибке «не удалось открыть поток».

function send($packet, $url) {
  $ctx = stream_context_create(
    array(
      'http'=>array(
        'header'=>"Content-type: application/x-www-form-urlencoded",
        'method'=>'POST',
        'content'=>$packet
      )
    )
  );
  return file_get_contents($url, 0, $ctx);
}

Ответы:


89

Попробуйте выполнить следующий сценарий, чтобы узнать, доступна ли оболочка https для ваших сценариев php.

$w = stream_get_wrappers();
echo 'openssl: ',  extension_loaded  ('openssl') ? 'yes':'no', "\n";
echo 'http wrapper: ', in_array('http', $w) ? 'yes':'no', "\n";
echo 'https wrapper: ', in_array('https', $w) ? 'yes':'no', "\n";
echo 'wrappers: ', var_export($w);

вывод должен быть примерно таким

openssl: yes
http wrapper: yes
https wrapper: yes
wrappers: array(11) {
  [...]
}

@volker Вот почему я попросил allow_url_fopen
Гордон

Что ж, странно то, что он говорит, что openssl отключен, но, согласно phpinfo (), он скомпилирован с ним, если я не вижу это неправильно.
Джеймс Симпсон,

phpinfo () сообщает вам об этом в строке конфигурации, или есть целый раздел под названием «OpenSSL»?
VolkerK

Хорошо, это просто в строке конфигурации, а не в разделе для этого. Полагаю, в этом проблема?
Джеймс Симпсон,

Все это у меня есть, но до сих пор не работает. И allow_url_fopen. Только URL-адреса без https работают с localhost.
Curtis

116

Чтобы разрешить оболочку https:

  • в php_opensslрасширение должно существовать и быть включено
  • allow_url_fopen должен быть установлен на on

В файле php.ini вы должны добавить эти строки, если они не существуют:

extension=php_openssl.dll

allow_url_fopen = On

Для обоих параметров в моей установке установлено значение «Вкл.», Но я все равно получаю сообщение об ошибке SSL «Предупреждение: file_get_contents (): SSL: время ожидания установления связи истекло»
Адамантус

53

Попробуйте следующее.

function getSslPage($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_REFERER, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

Примечание. Это отключает проверку SSL, что означает потерю безопасности, предлагаемой HTTPS . Используйте этот код только для тестирования / локальной разработки, никогда в Интернете или других общедоступных сетях. Если этот код работает, это означает, что сертификат SSL не является доверенным или не может быть проверен, что вам следует рассмотреть как отдельную проблему.


29
Зачем отключать проверку ssl при обработке кредитных карт?
Питер

Спасибо, хитрость здесь: curl_setopt ($ ch, CURLOPT_SSL_VERIFYPEER, FALSE);
Dylan B

46
$url= 'https://example.com';

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

$response = file_get_contents($url, false, stream_context_create($arrContextOptions));

Это позволит вам получать контент с URL-адреса, будь то HTTPS.


Спасибо! Это сработало с моей стороны. Пытался вызвать FB Open Graph API :)
decodingpanda

Я пытался получить доступ к своему домену с недействительным сертификатом только в тестовых целях, и хотя это отключает проверку SSL, это было то, что мне нужно.
Carla

Большой! Я уже 5 дней пытаюсь загрузить календарь airbnb на свой тестовый сайт XAMPP с помощью file_get_contents, это решило проблему, спасибо.
JohnnyBeGood

Сработал для меня, пытаясь подключиться к тестовой коробке Vagrant без действительного HTTP-сертификата через https. Ссылка на параметры контекста PHP SSL, устанавливаемые здесь: php.net/manual/en/context.ssl.php ; verify peer = Требовать проверки используемого сертификата SSL; verify_peer_name = Требовать проверки имени узла.
Энтони

Разве это не нарушение сертификата SSL, а брешь в безопасности?
webchun

10

Вероятно, это связано с тем, что на вашем целевом сервере нет действующего сертификата SSL.


У запрашивающего сервера не обязательно должен быть сертификат SSL.
ceejayoz

15
Я не сказал запрашивающий сервер, я сказал целевой сервер.
Эмиль Викстрём

2
Это научит меня бегло просматривать. Хех! Примите мои извинения и проголосуйте за.
ceejayoz

У целевого сервера есть действующий сертификат SSL.
Джеймс Симпсон

@ Джеймс, вы получите сообщение об ошибке, если вместо этого попытаетесь подключиться с помощью cURL? Или это совершенно невозможно попробовать?
Эмиль Викстрём

6

Просто добавьте две строки в свой файл php.ini.

extension=php_openssl.dll

allow_url_include = On

он работает для меня.


1
Вы, наверное, имеете в виду, allow_url_fopenпоскольку вопрос касается открытия URL, не включая.
shukshin.ivan

5

У меня была такая же ошибка. Установка allow_url_include = Onв php.iniфиксированной для меня.


5

HTTPS поддерживается, начиная с PHP 4.3.0, если вы скомпилировали поддержку OpenSSL. Также убедитесь, что у целевого сервера есть действующий сертификат, брандмауэр разрешает исходящие соединения, а allow_url_fopenв php.ini установлено значение true.


У меня PHP 5.2.8 с поддержкой OpenSSL. Я получаю ту же ошибку, и у целевого сервера есть действующий сертификат.
Джеймс Симпсон

2
настроен ли брандмауэр на разрешение исходящих https-соединений? Обычно веб-сервер, на котором запущен https, не работает на порту 80. Есть ли что-нибудь еще в ошибке, кроме «не удалось открыть поток»?
Гордон

1
Насколько я знаю, это вся ошибка: Предупреждение: fopen (https: // ...) [function.fopen]: не удалось открыть поток: нет такого файла или каталога в / home / user / public_html / test.php на строке 993
Джеймс Симпсон,

и что установлено в allow_url_fopen в php.ini?
Гордон

Странно. Можете ли вы выполнить GET по URL-адресу HTTP и HTTPS, чтобы узнать, работает ли это? без контекста потока?
Гордон,

3

В моем случае проблема была связана с тем, что WAMP использовал другой php.ini для CLI, чем Apache, поэтому ваши настройки, сделанные через меню WAMP, не применяются к CLI. Просто измените CLI php.ini, и он заработает.


1

Иногда сервер предпочитает не отвечать на основании того, что он видит или не видит в заголовках HTTP-запроса (например, соответствующий пользовательский агент). Если вы можете подключиться к браузеру, возьмите заголовки, которые он отправляет, и имитируйте их в контексте вашего потока.


0

Я застрял с нефункциональным https на IIS. Решено с помощью:

file_get_contents ('https ..) не загружается.

  • скачать https://curl.haxx.se/docs/caextract.html
  • установить под ..phpN.N / extras / ssl
  • отредактируйте php.ini с помощью:

    curl.cainfo = "C: \ Program Files \ PHP \ v7.3 \ extras \ ssl \ cacert.pem" openssl.cafile = "C: \ Program Files \ PHP \ v7.3 \ extras \ ssl \ cacert.pem"

Ну наконец то!


-1

ЧТОБЫ ПРОВЕРИТЬ, РАБОТАЕТ ЛИ URL

Код в вашем вопросе можно переписать как рабочую версию:

function send($packet=NULL, $url) {
// Do whatever you wanted to do with $packet
// The below two lines of code will let you know if https url is up or not
$command = 'curl -k '.$url;
return exec($command, $output, $retValue);
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.