Jak zmusić file_get_contents () do pracy z HTTPS?

106

Pracuję nad skonfigurowaniem przetwarzania kart kredytowych i muszę zastosować obejście dla CURL. Poniższy kod działał dobrze, gdy korzystałem z serwera testowego (który nie wywoływał adresu URL SSL), ale teraz, gdy testuję go na działającym serwerze z HTTPS, kończy się niepowodzeniem z komunikatem o błędzie „nie udało się otworzyć strumienia”.

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);
}
James Simpson
źródło

Odpowiedzi:

89

Wypróbuj poniższy skrypt, aby sprawdzić, czy jest dostępne opakowanie https dla twoich skryptów 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);

wyjście powinno wyglądać mniej więcej tak

openssl: yes
http wrapper: yes
https wrapper: yes
wrappers: array(11) {
  [...]
}
VolkerK
źródło
@volker Dlatego poprosiłem o allow_url_fopen
Gordon
Cóż, dziwne jest to, że mówi, że openssl jest wyłączone, ale zgodnie z phpinfo () jest z nim skompilowane, chyba że widzę to źle.
James Simpson
phpinfo () powie ci to w linii konfiguracji, czy też jest cała sekcja o nazwie „OpenSSL”?
VolkerK
Okay, to jest tylko w konfiguracji, a nie w jej sekcji. Myślę, że to jest problem?
James Simpson
Mam to wszystko i nadal nie działa. I allow_url_fopen. Tylko adresy URL inne niż https działają z lokalnego hosta.
Curtis,
116

Aby zezwolić na opakowanie https:

  • php_opensslrozszerzenie musi istnieć i być włączony
  • allow_url_fopen musi być ustawiony na on

W pliku php.ini powinieneś dodać te linie, jeśli nie istnieje:

extension=php_openssl.dll

allow_url_fopen = On
hassan
źródło
Obie są włączone w mojej instalacji, ale nadal
pojawia się
53

Spróbuj wykonać następujące czynności.

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;
}

Uwaga: wyłącza weryfikację SSL, co oznacza, że bezpieczeństwo oferowane przez HTTPS zostaje utracone . Używaj tego kodu tylko do testowania / lokalnego programowania, nigdy w Internecie lub innych sieciach publicznych. Jeśli ten kod działa, oznacza to, że certyfikat SSL nie jest zaufany lub nie można go zweryfikować, co należy rozwiązać jako osobny problem.

Benjamin Crouzier
źródło
29
Dlaczego miałbyś wyłączyć weryfikację SSL podczas przetwarzania kart kredytowych?
Peter
Dziękuję, sztuczka jest tutaj: 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));

Umożliwi to pobranie treści z adresu URL, niezależnie od tego, czy jest to HTTPS

Dushyant Dagar
źródło
Dzięki! To zadziałało na mój koniec. Próbowałem wywołać FB Open Graph API :)
decodingpanda
Próbowałem uzyskać dostęp do mojej domeny z nieprawidłowym certyfikatem tylko w celach testowych i chociaż to wyłącza weryfikację SSL, tego potrzebowałem.
Carla
Wspaniały! Od 5 dni próbuję pobrać kalendarz airbnb z mojej witryny testowej XAMPP za pomocą pliku_get_contents. Dzięki temu problem został rozwiązany.
JohnnyBeGood
Udało mi się połączyć się z urządzeniem testowym Vagrant bez ważnego certyfikatu HTTP przez https. Link do ustawianych tutaj opcji kontekstu PHP SSL: php.net/manual/en/context.ssl.php ; verify peer = Wymagaj weryfikacji używanego certyfikatu SSL; verify_peer_name = Wymagaj weryfikacji nazwy partnera.
Anthony
czy nie jest to zerwanie certyfikatu SSL i czy jest to luka w zabezpieczeniach?
webchun
10

Jest to prawdopodobnie spowodowane tym, że serwer docelowy nie ma ważnego certyfikatu SSL.

Emil Vikström
źródło
Serwer wysyłający żądanie nie musi mieć certyfikatu SSL.
ceejayoz
15
Nie powiedziałem serwera żądającego, powiedziałem serwer docelowy.
Emil Vikström
2
To nauczy mnie przeglądać. Heh! Proszę przyjąć moje przeprosiny i zagłosować.
ceejayoz
Serwer docelowy ma ważny certyfikat SSL.
James Simpson
@James, czy podczas próby połączenia z cURL pojawia się błąd? A może jest to absolutnie niemożliwe?
Emil Vikström
6

Po prostu dodaj dwie linie do pliku php.ini.

extension=php_openssl.dll

allow_url_include = On

to działa dla mnie.

Ritesh Chandora
źródło
1
Prawdopodobnie masz na myśli, allow_url_fopenponieważ pytanie dotyczy otwierania adresu URL, bez uwzględniania.
shukshin.ivan
5

Miałem ten sam błąd. Ustawienie allow_url_include = Onna php.inistałe to dla mnie.

Jim Jones
źródło
5

HTTPS jest obsługiwany począwszy od PHP 4.3.0, jeśli skompilowałeś obsługę OpenSSL. Upewnij się również, że serwer docelowy ma ważny certyfikat, zapora sieciowa zezwala na połączenia wychodzące, allow_url_fopenaw php.ini jest ustawiona na true.

Gordon
źródło
Mam PHP 5.2.8 z obsługą OpenSSL. Otrzymuję ten sam błąd, a serwer docelowy ma ważny certyfikat.
James Simpson
2
czy firewall jest skonfigurowany tak, aby zezwalał na wychodzące połączenia HTTPS? Zwykle serwer WWW z protokołem https nie działa na porcie 80. Czy w błędzie jest coś jeszcze oprócz „nieudanego otwarcia strumienia”?
Gordon
1
O ile wiem, to jest cały błąd: Ostrzeżenie: fopen (https: // ...) [function.fopen]: nie udało się otworzyć strumienia: nie ma takiego pliku lub katalogu w / home / user / public_html / test.php w linii 993
James Simpson
a allow_url_fopen w php.ini jest ustawione na co?
Gordon
To dziwne. Czy możesz wykonać GET na adresach URL HTTP i HTTPS, aby sprawdzić, czy to działa? bez kontekstu strumienia?
Gordon
3

W moim przypadku problem wynikał z tego, że WAMP używał innego php.ini dla CLI niż Apache, więc ustawienia dokonane za pomocą menu WAMP nie dotyczą CLI. Po prostu zmodyfikuj CLI php.ini i działa.

dtbarne
źródło
1

Czasami serwer nie odpowiada na podstawie tego, co widzi lub czego nie widzi w nagłówkach żądań http (na przykład odpowiedni agent użytkownika). Jeśli możesz połączyć się z przeglądarką, chwyć wysyłane przez nią nagłówki i naśladuj je w kontekście swojego strumienia.

GZipp
źródło
0

Utknąłem z niedziałającym protokołem HTTPS w usługach IIS. Rozwiązany:

file_get_contents („https ..) nie wczytuje się.

  • pobierz https://curl.haxx.se/docs/caextract.html
  • zainstaluj pod ..phpN.N / extras / ssl
  • edytuj php.ini za pomocą:

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

Wreszcie!

Teson
źródło
-1

ABY SPRAWDZIĆ, CZY URL JEST, CZY NIE JEST

Kod w Twoim pytaniu można przepisać do działającej wersji:

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);
}
Zwykły człowiek
źródło