web-dev-qa-db-ja.com

file_get_contents():SSL操作はコード1で失敗しました

私が作成したRESTページから、この特定のPHPサービスにアクセスしようとしています。私はこれらの2行に問題を絞り込んだ。だから私の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行目で次のエラーで終了します。

  • Warning:file_get_contents():SSL操作はコード1で失敗しました。
    • Warning:file_get_contents():2行目の... phpで暗号化を有効にできませんでした
    • 警告: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):ストリームを開けませんでした:操作に失敗しました... 2行目のphp

Gentooサーバを使っています。最近、PHPバージョン5.6にアップグレードしました。この問題が発生したのはアップグレード後でした。

RESTサービスをhttps://www.google.comのようなアドレスに置き換えたときに見つかりました。私のページはちょうどうまく動きます。

以前の試みで“verify_peer”=>falseを設定し、それをfile_get_contentsへの引数として渡しました。ここで説明します。 file_get_contentsはverify_peerを無視します=> false? しかし、作家が指摘したように。違いはありませんでした。

Php.iniファイルに次の行があるかどうか、サーバー管理者に確認します。

  • extension = php_openssl.dll
  • allow_url_fopen =オン

彼は私たちにGentooを使っているのでopensslはビルド時にコンパイルされると私に言った。 php.iniファイルには設定されていません。

allow_url_fopenが機能していることも確認しました。この問題は特殊な性質のためです。私は助けになる多くの情報を見つけていません。このようなことに遭遇したことがありますか?ありがとう。

152
Joe

これは非常に役に立つリンクでした:

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

PHP 5.6でsslを開くための変更を説明した公式文書ここから、falseに設定する必要があるもう1つのパラメータについて学びました。 "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; ?>
259
Joe

検証をオフにするだけではいけません。むしろ、あなたは証明書バンドルをダウンロードすべきです、おそらく curl バンドルはするでしょうか?

それから、あなたはそれをあなたのWebサーバーに置く必要があります、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バンドルに入っていることです。そうでない場合は、サイトのルート証明書を取得してそれを証明書ファイルに入れるまで、これは機能しません。

130
elitechief21

OpenSSLが私のマシンにインストールされていることを確認してphp.iniに追加することでこれを修正しました。

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

この問題を回避するには、次のように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;

}

Httpsで始まるURLを呼び出すときは、file_get_contents_curlの代わりにfile_get_contentsを使用してください。

12
Ben Shoval

PHPのバージョンが5の場合は、端末に次のコマンドを入力してcURLをインストールしてください。

Sudo apt-get install php5-curl
11
ARUNBALAN NV

基本的に、環境変数SSL_CERT_FILEを次のリンクからダウンロードしたssl-certificateのPEMファイルのパスに設定する必要があります。 http://curl.haxx.se/ca/cacert.pem

これを理解するのに私は多くの時間がかかりました。

7
Kshitij Mittal

以下の手順に従って、この問題を解決してください。

  1. このリンクからCA証明書をダウンロードします。 https://curl.haxx.se/ca/cacert.pem
  2. Php.iniを見つけて開きます
  3. curl.cainfoを探して、証明書をダウンロードした場所に 絶対パス を貼り付けます。 curl.cainfo ="C:\wamp\htdocs\cert\cacert.pem"
  4. WAMP/XAMPP(Apacheサーバ)を再起動してください。
  5. できます!

それが役立つことを願っています!

6
shakee93

私は同じ問題に遭遇したので、これに加えたいと思っただけで私はどこにも動くことができませんでした(例:cacert.pemファイルのダウンロード、php.iniでのcafileの設定など)。

NGINXを使用していて、SSL証明書に「中間証明書」が付属している場合は、中間証明書ファイルをメインの「mydomain.com.crt」ファイルと組み合わせる必要があります。これでうまくいくはずです。 Apacheには中間証明書専用の設定がありますが、NGINXにはありませんので、通常の証明書と同じファイル内になければなりません。

5
SlickTheNick

私のために働いて、私はPHP 5.6を使っています。 openssl拡張機能を有効にして、google map api verify_peerを呼び出すときにfalseに設定する必要があります。

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

 $response = file_get_contents("https://maps.googleapis.com/maps/api/geocode     /json?latlng=" . $latitude . "," . $longitude . "&sensor=false&key=" . Yii::$app->params['GOOGLE_API_KEY'], false, stream_context_create($arrContextOptions));

echo $response; ?>
3
Dipti

" https:// localhost/ ..." - ファイルを作成しようとしている自己署名証明書を使用して、私の開発者のマシン(php 7、Windows上のxampp)にも同じssl問題があった。明らかに、ルート証明書アセンブリ(cacert.pem)は機能しませんでした。ダウンロードしたcacert.pemのApache server.crtファイルからコードを手動でコピーし、php.iniのopenssl.cafile = path/to/cacert.pemエントリを作成しただけです。

3
hangerer

XAMPPとOSXのPHP 7で同じエラーが発生しました。

https://stackoverflow.com/ にある上記の答えは良いですが、それは私にとって問題を完全には解決しませんでした。 file_get_contents()が再び機能するようにするために、完全な証明書チェーンを提供する必要がありました。それが私のやり方です。

ルート証明書/中間証明書の取得

まず最初に、ルートandが中間証明書であることを理解しなければなりませんでした。

最も便利な方法は、おそらく ssl-shopper のようなオンラインの証明ツールです。

そこに私は3つの証明書、1つのサーバー証明書と2つのチェーン証明書(1つはルート、もう1つは明らかに中間)を見つけました。

私がする必要があるのは単にそれらの両方をインターネットで検索することだけです。私の場合、これがルートです。

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

今、それらをすべてまとめてください

それでは、それらすべてを1つのファイルにマージしてください。 (たぶん、それらを1つのフォルダに入れるだけでいいのですが、それらを1つのファイルにマージしただけです)。あなたはこれのようにそれをすることができます:

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はcertファイルを探しています。そしてこのパラメータがあり、それは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なしで、そしてうまくいけばセキュリティ上の欠陥なしで。

3
n.r.

このエラーの原因は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);
}
3
cweiske

Phpをphp5.6にアップデートした後、centOSでこの問題の犠牲になった後、私にはうまくいく解決策を見つけました。

これでデフォルトで置かれるべきあなたの証明書のための正しいディレクトリを入手してください

php -r 'print_r(openssl_get_cert_locations());' | grep '\[default_cert_file\]' | awk '{print $3}'

それから、これを使って証明書を取得し、それを上のコードから見つけたデフォルトの場所に置きます。

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

と同様のエラーについて

[11-May-2017 19:19:13アメリカ/シカゴ] PHP警告:file_get_contents():SSL操作がコード1で失敗しました。OpenSSLエラーメッセージ:エラー:14090086:SSLルーチン:ssl3_get_server_certificate:証明書の検証失敗しました

Opensslが参照するcertとディレクトリの権限を確認しましたか?

あなたはこれを行うことができます

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"フォルダには755のアクセス許可があるはずの700のアクセス許可があることに気付くまで、この問題はしばらく私をいらいらさせました。覚えておいて、これはキーのフォルダではなく証明書です。私はこれを読むことをお勧めします SSLアクセス権に関するこのリンク。

一度やった

chmod 755 certs

とにかく、少なくとも私にとっては、問題は修正されました。

1
Aleks

wgetまたはfile_get_contentsを使用するとき、私は別の安全なページに同じ問題がありました。 CurlとPHP-Curlのインストール - CurlとPHP-Curlのインストール - 多くの研究(この質問に対するいくつかの回答を含む)は簡単な解決策をもたらしました。

CurlとPHP-Curlアドオンをインストールしてから、Apacheを再起動してください。

Sudo apt-get install curl
Sudo apt-get install php-curl
Sudo /etc/init.d/Apache2 reload

すべてうまくいっています。

0
Aubs

もう1つ試すことは、ca-certificatesをdetailed here として再インストールすることです。

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

そしてもう一つ試すべきことは、 here のように問題のあるサイトの証明書を明示的に許可することです(特に、そのサイトがあなた自身のサーバーで、すでに.pemに手が届いている場合)。

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

CentOS 6でSO 5.6にアップグレードした後に、更新が必要な可能性がある安価なセキュリティ証明書を持つサーバー自体にアクセスしようとした後、この正確なPHPエラーに遭遇しましたletsencrypt証明書をインストールして、上記の2つのステップでそれはうまくいきました。 2番目のステップが必要だった理由はわかりません。


便利なコマンド

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
0
site