SoapClientでhttps通信を行う際の鍵指定について


PHPでSoapClientを使用してSOAPサーバー(JAVA)にhttpsで接続したいのですがエラーが発生し接続が出来ません

□ソースコード
$soap = \SoapClient("soapサーバーURL", array("local_cert" => "soapサーバー証明書.jks"));
□エラー内容
parsing wsdl couldn't load from failed to load external entity

鍵の形式が違うのかと思い、ネットで調べてみるとlocal_certに指定しているのは全てpem拡張子のファイルでした。
local_certに指定する鍵は通信先(SOAPサーバー)の鍵でしょうか?
また指定する鍵はpem形式でなくてはだめでしょうか?
もしかしたら接続元の方の鍵を指定するのかと思い、
接続元のpem形式のファイルを指定してみたのですがだめでした。
接続元:opensslの自己認証でhttps可です
接続先:keytoolで作成してhttps可です
宜しくお願いします

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2012/10/08 22:04:51
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:JULY No.1

回答回数966ベストアンサー獲得回数247

ポイント400pt

local_certに指定する鍵は通信先(SOAPサーバー)の鍵でしょうか?

違います。

PHP: SoapClient::SoapClient - Manual
options の説明の中に

HTTPS クライアント証明書による認証には local_cert と passphrase を使用します。

と書かれています。

SSL/TLS で通信を行う場合、通常は、サーバの証明書を使って通信を暗号化するのですが、クライアント側からクライアント自身の証明書を送って、そのクライアントがつながることを許可するかどうかを判断する、という事が可能です。これが「クライアント証明書による認証」です。
電子証明書を使ったセキュアなクライアント認証のしくみ - インターネットコム

もし、クライアント証明書を使った認証処理をする事を考えているのであれば、local_cert に指定するのは、クライアントの証明書です。そうではなくて、単に https で通信したいのであれば、local_cert の指定は必要ありません。

他1件のコメントを見る
id:JULY

間違って、oil999 さんの回答の下にコメントを書いていたので、改めて自分の回答の下に書きます。

自己証明書なのに、クライアント側で証明書のエラーが発生しない件ですが、どうやら、デフォルトの挙動がそうみたいです。

SoapClient のマニュアルページに、さらっと、stream_context オプションの話がでていますが、通信の条件等を設定したければ、この stream_context オプションに、別途生成した stream_cpmtext を指定できるようです。

http://stackoverflow.com/questions/8443618/disable-certificate-verification-in-php-soapclient
上記ページは、「サーバ証明書の検証を無効にするにはどうすれば良いのか?」という質問なのですが、解答欄にある PHP のソースが、この stream_context オプションの使い方の参考になるでしょう。

で、上記のサンプルコードだと、意図的に証明書の検証を無効にするために、verify_peer を false にする、という事をしていますが、SSL コンテキストのマニュアルを読むと、デフォルトで無効だと書いてあります。
http://php.net/manual/ja/context.ssl.php

ひょっとしたら、PHP のバージョンや、ディストリビューションによってデフォルト値が違う事があるかもしれませんが、このマニュアル読む限り、意図的に verify_peer を true とした stream_context を作って SoapClient に指定しない限り、サーバ証明書の検証は行われないものと思われます。

2012/10/05 11:37:30
id:akihiko0826

JULY様

ご回答して下さいまして有難うございます。
SSL通信には必ず証明書の検証をしなければ行けないのだと思ってたのですが、
SoapClientの場合デフォルトの設定だと証明書の検証をしないんですね。
また、サンプルコードのサイトを教えて下さいまして有難うございます。
stream_contextの指定など初めてしり、とても勉強になります。

2012/10/06 15:51:25

その他の回答2件)

id:JULY No.1

回答回数966ベストアンサー獲得回数247ここでベストアンサー

ポイント400pt

local_certに指定する鍵は通信先(SOAPサーバー)の鍵でしょうか?

違います。

PHP: SoapClient::SoapClient - Manual
options の説明の中に

HTTPS クライアント証明書による認証には local_cert と passphrase を使用します。

と書かれています。

SSL/TLS で通信を行う場合、通常は、サーバの証明書を使って通信を暗号化するのですが、クライアント側からクライアント自身の証明書を送って、そのクライアントがつながることを許可するかどうかを判断する、という事が可能です。これが「クライアント証明書による認証」です。
電子証明書を使ったセキュアなクライアント認証のしくみ - インターネットコム

もし、クライアント証明書を使った認証処理をする事を考えているのであれば、local_cert に指定するのは、クライアントの証明書です。そうではなくて、単に https で通信したいのであれば、local_cert の指定は必要ありません。

他1件のコメントを見る
id:JULY

間違って、oil999 さんの回答の下にコメントを書いていたので、改めて自分の回答の下に書きます。

自己証明書なのに、クライアント側で証明書のエラーが発生しない件ですが、どうやら、デフォルトの挙動がそうみたいです。

SoapClient のマニュアルページに、さらっと、stream_context オプションの話がでていますが、通信の条件等を設定したければ、この stream_context オプションに、別途生成した stream_cpmtext を指定できるようです。

http://stackoverflow.com/questions/8443618/disable-certificate-verification-in-php-soapclient
上記ページは、「サーバ証明書の検証を無効にするにはどうすれば良いのか?」という質問なのですが、解答欄にある PHP のソースが、この stream_context オプションの使い方の参考になるでしょう。

で、上記のサンプルコードだと、意図的に証明書の検証を無効にするために、verify_peer を false にする、という事をしていますが、SSL コンテキストのマニュアルを読むと、デフォルトで無効だと書いてあります。
http://php.net/manual/ja/context.ssl.php

ひょっとしたら、PHP のバージョンや、ディストリビューションによってデフォルト値が違う事があるかもしれませんが、このマニュアル読む限り、意図的に verify_peer を true とした stream_context を作って SoapClient に指定しない限り、サーバ証明書の検証は行われないものと思われます。

2012/10/05 11:37:30
id:akihiko0826

JULY様

ご回答して下さいまして有難うございます。
SSL通信には必ず証明書の検証をしなければ行けないのだと思ってたのですが、
SoapClientの場合デフォルトの設定だと証明書の検証をしないんですね。
また、サンプルコードのサイトを教えて下さいまして有難うございます。
stream_contextの指定など初めてしり、とても勉強になります。

2012/10/06 15:51:25
id:oil999 No.2

回答回数1728ベストアンサー獲得回数320

ポイント100pt

local_certに指定する鍵は通信先(SOAPサーバー)の鍵でしょうか?

違います。クライアント証明書(接続元の証明書)です。

証明書ファイルはpem形式のものです。
質問ではjksになっていますが、ご確認下さい。
keytoolでRSAキーペアは作成しましたか?
keytoolのエクスポートはDERです。opensslでpemに変換しましたか?

id:akihiko0826

>違います。クライアント証明書(接続元の証明書)です。
>証明書ファイルはpem形式のものです。
>質問ではjksになっていますが、ご確認下さい。
>keytoolでRSAキーペアは作成しましたか?
>keytoolのエクスポートはDERです。opensslでpemに変換しましたか?
ご回答頂きまして有難うございます。
クライアント証明書とサーバ証明書について種類があるのを知らず、
ずっと、local_certにはSoapサーバー側の鍵を指定しなければ、行けないと思いjksを指定してしまっていました。
なのでlocal_certは特に指定する必要は無かったです。


はい、keytoolでRSAキーペアは作成しております。
実際には試した際、サーバー側のファイルをlocal_certに指定したりしていたので、
そもそも間違ってる事をやっていたのですがopensslでpemに変換しました。

2012/10/05 01:05:03
id:akihiko0826

すみません、厚かましいのですがもう一つ質問させて頂けないでしょうか。

現在は、送信先(Soapサーバ)への接続が出来るようになりました。

ただ、サーバ側の証明書をクライアント側(PHPが入っているSoap接続元)でインストールしていないのに、

警告なしでSoapサーバに接続出来る理由がどうしても分かりません。

今回はサーバ証明書を使用してSSL通信する方法になります。

下記構成になります。

1.ユーザーがブラウザでWEBサイト(PHP)にアクセスします。

2.WEBサイト(PHP)の内部処理でSoapClientを使用して、Soapサーバ(JAVA)へ接続し、必要な情報を取得します。

サーバー・クライアント間でSSL通信を行う場合、

サーバー側がサーバ証明書をクライアント側に送り、

クライアント側ではルート証明書を元に、サーバから送られてきた証明書を

検証し、問題なければ中に入っている公開鍵を使用して情報を暗号化し、

サーバー側へリクエストを送り、サーバー側では自身の秘密鍵で復号する

とネットに載っていました。

これについては何となくですがイメージはつくのですが、

クライアント側ではルート証明書を持っていなければ行けません。

今回、Soapサーバ側の証明書はkeytoolで作成した自己証明書になります。

今回サーバ側がJAVAがインストールされているサーバー(Soap通信接続先)で、

クライアント側がPHPが入っているサーバー(Soap通信接続元)になるかと思いますが、

クライアント側ではとくに証明書のインストール等していません。

そもそも、SoapClientを使用してhttpsのSoap通信を行う場合は、

Soapサーバ側の証明書や鍵情報などは意識せずに接続出来るのが

正しい動きなのでしょうか。

重ね重ねの質問で恐縮なのですが、

何卒、宜しくお願い致します。

id:sanada33 No.3

回答回数293ベストアンサー獲得回数3

ポイント30pt

一回といあわせてはいかがでしょうか

id:akihiko0826

sanada33様

コメントして頂きまして有難うございます。
JULY様がコメントして下さったようにサーバー間でSSL通信を行う際、
証明書の検証を行わない動作をしておりました。
また他のSSL関連の質問でも、PHPのSSL通信時にはサーバー側の証明書については
デフォルトでは証明書の検証は行わないという記載がありました。
http://q.hatena.ne.jp/1209101645

証明書の検証自体は行われてはないですが、サーバー間の暗号自体は行われているようでしたので安心致しました。

2012/10/08 22:02:34

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません