web-dev-qa-db-ja.com

soapclientを使用してhttpsホストに接続する:SSLの問題を修正する方法は?

TLDR

SoapClientでhttpsエンドポイントに接続できないようです。私のwgetがhandshake failureを返すので、それが原因だと思います。

どうすればSOAP PHPを使用してこのサーバーにリクエストできますか?

コンプリート

SOAPサーバー(https)に接続しようとしています。クライアント証明書認証がないため、接続は非常に簡単ですが、残念ながらそうではありません。

問題は、Could not connect to Hostメッセージが表示され続けることです。

私が使用している接続方法は別のサーバーで機能しており、このサーバーの場所を正しく設定していることを確認しました(自分が制御するサーバーに変更したところ、そこで応答があります)。サーバーへのhttps/ssl接続に問題があると思われます。

状況

  • ローカルにあるwsdlに基づいてPHP Soapclientを作成しています。
  • エンドポイントを変更すると、RequestヘッダーとResponseヘッダーが表示され、すべてが期待どおりに機能します。
  • wgetを使用してマシンに接続すると問題が発生しますが、サーバーからマシンにアクセスできます(以下を参照)SSL接続を確立できません。
  • この問題は、openssl接続でも確認できます(以下を参照)

私が試したこと。

「接続がない!」という話題はたくさんありますが、明らかに「ルーターが悪かった、アドレスにタイプミスをしたなど」が多発しています。私は何度も提案されたこれらの設定を試しましたが、実際の理由から、「それが機能しなかったことを確認するための「カットアンドペースト」ソリューション」としてより多くのものを追加しました。

Wsdlオプション用にstream_contextを作成します。私が試してみました

$context = stream_context_create(
              array(
                'ssl' => array(
                           'verify_peer' => false,  //default
                           'allow_self_signed' => true, //needs verify peer, tried that
                           'ciphers'=>"SHA1", // quite random.
                   ),
                'https' => array(
                           'curl_verify_ssl_peer'  => false,
                           'curl_verify_ssl_Host'  => false
                          )
      )
            );
$options['stream_context'] = $context;

(最初はverify_peerallow_self_signedsslオプションのみ。次にhttps配列を追加し、最後にciphersキーをsslに追加しました。)

このバグ への参照を見つけましたが、1)その警告が表示されない、2)プロキシ関連のようです、3)私のバージョンにはもうバグがないはずです。 php 5.3.10を実行しています

URLを取得しようとすると、次のようになります。

    wget https://[[servername]]/SOAP
    Resolving [[servername]] ([[servername]])... xxx.xxx.xxx.xxx
    Connecting to [[servername]]([[servername]])|xxx.xxx.xxx.xxx|:443... connected.
    OpenSSL: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure

Opensslに接続しようとすると、次のようになります。

$ openssl s_client -connect [[server]]:443 -state
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:unknown state
SSL3 alert read:fatal:handshake failure
SSL_connect:error in unknown state
3074463944:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:724:

しかし、ssl3を強制すると、期待どおりの結果が得られます

$ openssl s_client -ssl3 -connect [[server]]:443 -state
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv3 write client hello A
SSL_connect:SSLv3 read server hello A
**happy certificate stuff. this is good**
Protocol  : SSLv3
Cipher    : DHE-RSA-AES256-SHA
**more happy certificate stuff. **

Ssl_versionを3に設定して この質問 からcurl-wrapperを追加しようとしました(これは上記のopensslコマンドで機能するようです)。そのラッパーはいくつかのパラメーターを破棄するので、これがどれほど完全になるかはわかりません。さらに、チェックを明示的にfalseに設定しない限り、ハンドシェイクエラーが発生します。これを行うと(以下を参照)、空の応答が返されます。

curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);

原因

上で述べたように、私はsslハンドシェイクを疑っていますが、それを修正する方法がわかりません。接続は別のwsdl、異なる場所が設定された同じwsdlなどで機能するため、wsdlまたはクライアント作成に問題があるとは思われません。問題を引き起こしているのは純粋にこの(https)エンドポイントです。

追加のテスト。

カールラッパーを使用した上記のテストと同じように、@ halfwarrがコメントで示唆しているように、最小限のSOAPエンベロープを送信してみました。 Alsは空の応答を返します。

したがって、上記では、サーバーからhttp 204を絞り出す方法があるようですが、それはほとんど成功していません。しかし、それは2番目の問題である可能性がありますか?わからない。

私はssl3を強制的に試す必要があると思いますが、どうすればよいかわかりません(これも間違ったパスである可能性があるため、 XY問題 ここでは:)

12
Nanne

面白い。これを追加してみてください:

wget https://[[SERVER]]/soap/ —post-file=request.xml —header=”Content-Type: text/xml” -O response.xml

これにより、結果がresponse.xmlという名前のファイルとして保存されます。

1
Matheno

最新バージョンPHP 5.5.3ではSSLバージョンを設定できます。stream_contextを使用できる他のユーザーを見てきましたが、それも機能しませんでした。

回避策とフェイルセーフとして、キャッチを使用してSOAPエンベロープリクエストを取得しました(上記でテストしたものと同様)。

$xml = $client->__getLastRequest()

そしてcurl経由で送信します:


curl_setopt($ch, CURLOPT_SSLVERSION, 3);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

それは私が少なくとも前進することを可能にします。

1
rdizzle

php_openssl.dllphp.iniを有効にしましたか?

参照:

PHP SOAP SSL WSDLソースに接続できません

0
Sid