file_get_contents (): Kod 1 ile SSL işlemi başarısız, Kripto etkinleştirilemedi


188

Sunucumuzda oluşturduğum bir PHP sayfasından bu özel REST hizmetine erişmeye çalışıyorum. Sorunu bu iki çizgiye daralttım. PHP sayfam şöyle:

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

Sayfa 2. satırda aşağıdaki hatalarla ölür:

  • Uyarı: file_get_contents (): SSL işlemi kod 1 ile başarısız oldu. OpenSSL Hata mesajları: hata: 14090086: SSL rutinleri: SSL3_GET_SERVER_CERTIFICATE: sertifika doğrulaması başarısız oldu ... 2. satırda php
    • Uyarı: file_get_contents (): Kripto girişi etkinleştirilemedi ... 2. satırdaki php
    • Uyarı: 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): akış açılamadı: işlem başarısız oldu ... 2. satırda php

Bir Gentoo sunucusu kullanıyoruz. Kısa süre önce PHP 5.6 sürümüne geçtik. Bu sorun ortaya çıktığında yükseltme sonrasında oldu.

REST hizmetini aşağıdaki gibi bir adresle değiştirdiğimde buldum https://www.google.com; sayfam gayet iyi çalışıyor.

Daha önceki bir denemede bunu “verify_peer”=>falseaçıkladım ve burada açıklandığı gibi file_get_contents için bir argüman olarak geçtim : file_get_contents verify_peer => false? Ancak yazarın belirttiği gibi; hiçbir fark yaratmadı.

Sunucu yöneticilerimizden birine php.ini dosyamızda bu satırların olup olmadığını sordum:

  • uzantısı = php_openssl.dll
  • allow_url_fopen = Açık

Bana Gentoo'da olduğumuzdan, inşa ettiğimizde openssl'nin derlendiğini söyledi; ve php.ini dosyasında ayarlanmadı.

Ayrıca allow_url_fopençalıştığını da doğruladım . Bu sorunun özelleşmiş yapısı nedeniyle; Yardım için fazla bilgi bulamıyorum. Herhangi biriniz böyle bir şeyle karşılaştınız mı? Teşekkürler.


Kaspersky kullanıyorsanız, şunu kontrol edin: stackoverflow.com/a/54791481/3549317
cespon

Yanıtlar:


344

Bu, bulmak için son derece yararlı bir bağlantıydı:

http://php.net/manual/en/migration56.openssl.php

PHP 5.6 ssl açmak için yapılan değişiklikleri açıklayan resmi bir belge Buradan Ben yanlış ayarlamam gereken bir parametre daha öğrendim: "verify_peer_name" => false

Not: Bunun çok önemli güvenlik etkileri vardır. Doğrulamanın devre dışı bırakılması, bir MITM saldırganının istekleri gizlemek için geçersiz bir sertifika kullanmasına izin verir . Bunu yerel kalkınmada yapmak yararlı olsa da, üretimde başka yaklaşımlar da kullanılmalıdır.

Yani benim çalışma kodum şöyle:

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

122
Bu SSL sertifikasını
ihlal eder

8
@ Hypery2k'in işaret ettiği gibi, yalnızca doğrulamayı devre dışı bırakmamalısınız. SSL kullanma amacını yenmeyen alternatif bir çözüm için cevabımı görün.
elitechief21

4
Bu gerçekten yapılmamalı. Sorunu yan adımdan ziyade düzeltmeniz gerekir. @ Elitechief21'den daha iyi çözümü görün.
Jasper

5
Yerel bir ortamdan bir API'ye karşı test ediyorsanız bu sinir bozucu olabilir. Bu durumda normalde doğrulamayı tıklarım.
HappyCoder

12
Bunu yapmaya çalıştığımda her zaman buraya geldiğim için, kolayca kopyalayıp yapıştırmak için kod:file_get_contents($url, false, stream_context_create(array('ssl' => array('verify_peer' => false, 'verify_peer_name' => false))));
laurent

154

Sadece doğrulamayı kapatmamalısınız. Bunun yerine bir sertifika paketi indirmelisiniz, belki de kıvrılma paketi yapacaktır?

Sonra sadece php çalıştıran kullanıcıya dosyayı okumak için izin vererek, web sunucunuza koymanız gerekir. O zaman bu kod sizin için çalışmalıdır:

$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));

Umarım, erişmeye çalıştığınız sitenin kök sertifikası kıvrılma demetindedir. Değilse, sitenin kök sertifikasını alıp sertifika dosyanıza yerleştirene kadar bu yine de çalışmaz.


.Crt dosyası nereden geliyor? Bukle web sitesinde sadece .pem'e sahip olduğunuz bağlantı yoktur.
vee

1
Pem dosyası aynı olmalıdır. Bu yayınlandığı sırada, sitelerinde sertifika paketinin iki sürümü vardı, bir pem ve bir crt ve sadece örneğim için crt dosyasını kullandım (doğal olarak kaldıracakları budur). İleride başvurmak üzere, crt dosyaları genellikle yeniden adlandırılan pem dosyalarıdır; bu dosyalar yeniden adlandırılır, böylece pencereler dosyayı bir sertifika dosyası olarak tanır. Bu her zaman böyle olmayacak, ama bu durumda. Örneğimi, şu anda curl sitesinde bulunan pem dosyasını kullanacak şekilde güncelleyeceğim
elitechief21

4
Ayrıca stream_context_set_defaulther zaman file_get_contents içine geçmek zorunda kalmamak için kullanılabilecek yararlı bir işlev
Ken Koch

Hiç kimse bunu işe aldı mı? Bu cevapta bağlı cacert.pem paketi ve ayrıca (doğrulamak istediğim sertifika için CA kökü olan) Comodo CA Kök sertifikası ile denedim, ancak her zaman başarısız olacaktır.
zmippie

1
Güvenlik açısından: Kafeterya akışı bağlamı seçeneğinin kullanılmasının yanında, şifreli akış içeriği seçeneğinde izin verilen şifreleri tanımlamak ve savunmasız olarak bilinen SSL sürümlerini yasaklamak da çok önemli olabilir. Ayrıca CRIME saldırı vektörünü azaltmak için tabaka bağlamı devre dışı bırakma_kompresyonunun true değerine ayarlanması önerilir.
Josef Glatz

36

Bu makinede OpenSSL yüklü olduğundan emin olmak ve sonra benim php.ini ekleyerek bu düzeltildi:

openssl.cafile=/usr/local/etc/openssl/cert.pem

@Akhi Google'da bazı eğiticiler bulabilmeniz gerekir
andlin

2
IIS'de PHP 7 kullanarak aynı yöntemi kullandım, cert.pemdosyayı php.iniopenssl.cafile=D:\Tools\GnuWin32\bin\cacert.pem
indirdim

1
PEM dosyasını curl.haxx.se/docs/caextract.html adresinden indirdim - Windows'ta belirli bir gstatic.com URL'si ile benim için sorunu çözdüm.
Jake

Curl.haxx.se/docs/caextract.html dosyasından PEM dosyasını indirmek benim için Centos 7'de işe yaramadı. Ana sertifikayı ve pkcs7'yi birleştirerek bir paket sertifikası oluşturup sunucuya yerleştirip daha sonra openssl.cafile yolunu belirledim. Doğru cevap ve yön için +1.
Arvind K.

Bir paket oluştururken, ana sertifikaya geçmeden önce pkcs'i pem dosyasına dönüştürmeyi unutmayın
Arvind K.

22

Bu sorunu, curl kullanan özel bir işlev yazarak aşağıdaki gibi çözebilirsiniz:

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;

}

Ardından , https ile başlayan bir URL'yi çağırmak file_get_contents_curlyerine kullanın file_get_contents.


Bu benim için çalıştı. Harika iş ve teşekkürler!
Nick Green

11

Benim için çalışıyorum, PHP 5.6 kullanıyorum. openssl uzantısı etkinleştirilmelidir ve google map çağrılırken api verify_peer yanlış yapmak Aşağıdaki kod benim için çalışıyor.

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

10

PHP sürümünüz 5 ise, terminale aşağıdaki komutu yazarak cURL kurmayı deneyin:

sudo apt-get install php5-curl

9
Bunun kesinlikle bir ilgisi yok cURL.
Andreas

2
Php kıvırmak yükleme doğru cevap olmalı! Mac sistemim için bağlantı noktasını kullanıyorum ve komut:sudo port install php70-curl
hailong


6

aşağıdaki adımları izleyerek bu sorunu çözebilirsiniz,

  1. CA Sertifikasını şu bağlantıdan indirin: https://curl.haxx.se/ca/cacert.pem
  2. Php.ini dosyasını bulun ve açın
  3. Sertifikayı indirdiğiniz mutlak yolu arayın curl.cainfove yapıştırın .curl.cainfo ="C:\wamp\htdocs\cert\cacert.pem"
  4. WAMP / XAMPP'yi (apache sunucusu) yeniden başlatın.
  5. İşe yarıyor!

umarım yardımcı olur !!


bu güvenli mi? kolay çözümleri seviyorum ama burada bazı bilgileri eksik im ..
swisswiss

test için sorun yok
Geomorillo

5

Ben sadece aynı soruna koştu ve hiçbir yerde bulabiliriz hiçbir şey işe yarayacağını (örneğin cacert.pem dosyasını indirmek, php.ini içinde cafile ayarı vb.) Beri bu eklemek istedim

NGINX kullanıyorsanız ve SSL sertifikanız bir "ara sertifika" ile birlikte geliyorsa, ara sertifika dosyasını ana "etkialanim.com.crt" dosyanızla birleştirmeniz gerekir ve çalışması gerekir. Apache'nin ara sertifikalar için özel bir ayarı vardır, ancak NGINX normal sertifikanızla aynı dosyada olması gerektiği için değildir.


4

Bu hatanın nedeni, PHP'nin güvenilir sertifika yetkilileri listesi olmamasıdır.

PHP 5.6 ve üstü sistem tarafından güvenilen CA'ları otomatik olarak yüklemeye çalışır. Bununla ilgili sorunlar düzeltilebilir. Daha fazla bilgi için http://php.net/manual/en/migration56.openssl.php adresine bakın .

PHP 5.5 ve önceki sürümleri doğru şekilde kurmak gerçekten zordur, çünkü her istek bağlamında CA paketini el ile belirtmeniz gerekir; Kodum için <5.6 sürümleri için SSL doğrulamasının devre dışı bırakılmasına karar verdim:

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

Bu, sorunumu bulmama yardımcı oldu. PHP 5.6 üzerinde olmama rağmen, yukarıdaki bağlantıya göre cafile bağlam seçeneğini kullanarak eski bir CA dosyasını elle belirten eski bir api istemci kütüphanesi kullanıyordum. Bunu api istemci kütüphanesinden kaldırmak benim için düzeltti. Muhtemelen PHP OpenSSLs güvenilir paketini kullanmaya başladı
Joe Lipson

4

XAMPP ve OSX üzerinde PHP 7 ile aynı hata vardı.

Https://stackoverflow.com/ adresinde yukarıda belirtilen cevap iyidir, ancak sorunu benim için tamamen çözmedi. Ben file_get_contents () tekrar çalışması için tam sertifika zinciri sağlamak zorunda kaldı. Ben böyle yaptım:

Kök / ara sertifika al

Her şeyden önce kök ve ara sertifikanın ne olduğunu bulmak zorundaydım .

En uygun yol belki de ssl-shopper gibi çevrimiçi bir sertifika aracıdır

Orada üç sertifika, bir sunucu sertifikası ve iki zincir sertifikası buldum (biri kök, diğeri görünüşte ara).

Tek yapmam gereken sadece ikisi için de internette arama yapmak. Benim durumumda, bu kök:

thawte DV SSL SHA256 CA

Ve url thawte.com yol açar . Bu yüzden bu sertifikayı bir metin dosyasına koydum ve ara madde için de aynısını yaptım. Bitti.

Ana makine sertifikasını alın

Yapmam gereken bir sonraki şey sunucu sertifikamı indirmektir. Linux veya OS X'te openssl ile yapılabilir:

openssl s_client -showcerts -connect whatsyoururl.de:443 </dev/null 2>/dev/null|openssl x509 -outform PEM > /tmp/whatsyoururl.de.cert

Şimdi hepsini bir araya getirin

Şimdi hepsini tek bir dosyada birleştirin. (Belki de onları tek bir klasöre koymak iyidir, sadece bir dosyada birleştirdim). Bunu şu şekilde yapabilirsiniz:

cat /tmp/thawteRoot.crt > /tmp/chain.crt
cat /tmp/thawteIntermediate.crt >> /tmp/chain.crt
cat /tmp/tmp/whatsyoururl.de.cert >> /tmp/chain.crt

PHP'ye zinciri nerede bulacağını söyle

PHP'nin sertifika dosyalarını nerede aradığını size söyleyecek bu kullanışlı fonksiyon openssl_get_cert_locations () vardır. Ve file_get_contents () 'ye sertifika dosyalarını nerede arayacağını söyleyen bu parametre vardır. Belki her iki yol da işe yarayacaktır. Parametre yolunu tercih ettim. (Yukarıda belirtilen çözüme kıyasla).

Şimdi bu benim PHP Kodum

$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));

Bu kadar. file_get_contents () tekrar çalışıyor. CURL olmadan ve umarım güvenlik açığı olmadan.


Dosya chain.pemnedir? Bu chain.crtmu?
Dr.X

Bu chain.crt değildir, asıl sertifika içindir. Ara sertifikaların, diğer bir deyişle sertifika zincirinin listesi. Mutlaka buna ihtiyacınız yoktur. İhtiyacınız olup olmadığını öğrenmek için bir SSL sertifika denetleyicisi kullanın. Öyleyse, doğru dosyayı bulmak için sertifika veren kuruluşunuzun adını + "zincir" veya "ara" terimini arayabilirsiniz.
nr

4

Php php5.6 için güncelledikten sonra centOS bu sorun kurban düştükten sonra benim için çalışan bir çözüm buldum.

Bunun için varsayılan olarak yerleştirilecek dizininiz için doğru dizini alın

php -r 'print_r(openssl_get_cert_locations()["default_cert_file"]);'

Ardından sertifikayı almak ve yukarıdaki kodda bulunan varsayılan konuma koymak için bunu kullanın

wget http://curl.haxx.se/ca/cacert.pem -O <default location>

3

" Https: // localhost / ..." - dosyasını açmaya çalışan kendinden imzalı bir sertifika ile geliştirici makinemde (php 7, Windows'ta xampp) aynı SSL sorunu vardı . Açıkçası kök sertifika derlemesi (cacert.pem) işe yaramadı. Ben sadece indirilen cacert.pem apache server.crt-File kodu manuel olarak kopyaladı ve php.ini openssl.cafile = yol / to / cacert.pem giriş yaptım


2

Denenecek başka bir şey, buradaca-certificates ayrıntılı olarak yeniden yüklenmektir .

# yum reinstall ca-certificates
...
# update-ca-trust force-enable 
# update-ca-trust extract

Ve denenecek başka bir şey, burada açıklandığı gibi söz konusu sitenin sertifikasına açıkça izin vermektir (özellikle bir site kendi sunucunuzsa ve zaten .pem'e eriştiyseniz).

# cp /your/site.pem /etc/pki/ca-trust/source/anchors/
# update-ca-trust extract

Belki de güncellenmesi gereken bir cheapsslsecurity sertifikası olan sunucuya erişmeye çalışarak CentOS 6 üzerinde PHP 5.6'ya yükselttikten sonra bu tam SO hatasını çalıştırıyordum, ancak bunun yerine bir letsencrypt sertifikası yükledim ve bu iki adımın üstünde Numara. İkinci adımın neden gerekli olduğunu bilmiyorum.


Yararlı Komutlar

Openssl sürümünü görüntüle:

# openssl version
OpenSSL 1.0.1e-fips 11 Feb 2013

PHP cli ssl geçerli ayarlarını görüntüle:

# 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

1

Şuna benzer hatalarla ilgili olarak

[11-May-2017 19:19:13 America / Chicago] PHP Uyarı: file_get_contents (): SSL işlemi kod 1 ile başarısız oldu. OpenSSL Hata mesajları: hata: 14090086: SSL rutinleri: ssl3_get_server_certificate: sertifika doğrulama başarısız

Openssl tarafından belirtilen sertifika ve dizinlerin izinlerini kontrol ettiniz mi?

Bunu yapabilirsiniz

var_dump(openssl_get_cert_locations());

Buna benzer bir şey elde etmek için

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) ""
}

Bu sorun, "certs" klasörümün 755 izni olması gereken 700 izni olduğunu fark edene kadar beni bir süre hayal kırıklığına uğrattı. Unutmayın, bu anahtarlar için klasörler değil sertifikalar. SSL izinlerinde bu bağlantıyı okumanızı tavsiye ederim .

Bir kez yaptım

chmod 755 certs

Sorun giderildi, en azından benim için her neyse.


Yaşasın! CHMOD da benim sorunumdu ;-) Teşekkürler
RA.

0

wgetVeya kullanırken başka bir güvenli sayfa için de aynı sorunu yaşadım file_get_contents. Birçok araştırma (bu soruya verilen yanıtların bazıları dahil) basit bir çözümle sonuçlandı - Curl ve PHP-Curl'u yükleme - Doğru anladıysam, Curl'un sorunu çözen Comodo için Kök CA'sı var

Curl ve PHP-Curl eklentisini yükleyin, ardından Apache'yi yeniden başlatın

sudo apt-get install curl
sudo apt-get install php-curl
sudo /etc/init.d/apache2 reload

Şimdi hepsi çalışıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.