web-dev-qa-db-ja.com

RESTクライアントとヘッダーを使用しているが、PostManでは正常に機能する場合にssl.SSLHandshakeExceptionを取得する

以下の詳細を持つ外部RESTリソースがあります:

  1. URL:abc.com/orders(ドメインはhttpsです)
  2. キー「user」の値が「abcd」のHTTPヘッダーとしてUserIDを渡す必要があります
  3. これはJSON応答を返します

私は以下のJavaコードを使用しています:

try {

            Client client = Client.create();

            WebResource webResource = client.resource("abc.com/orders");

            ClientResponse response = webResource.header("user", "abcd").accept("application/json")
                    .get(ClientResponse.class);

            if (response.getStatus() != 200) {
                throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
            }

            String output = response.getEntity(String.class);

            System.out.println("Output from Server .... \n");
            System.out.println(output);

        } catch (Exception e) {

            e.printStackTrace();

        }

しかし、PostManで正常に動作しますが、例外を下回っています。

com.Sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: Sun.security.validator.ValidatorException: PKIX path building failed: Sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at com.Sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.Java:155)
    at com.Sun.jersey.api.client.Client.handle(Client.Java:652)
    at com.Sun.jersey.api.client.WebResource.handle(WebResource.Java:682)
    at com.Sun.jersey.api.client.WebResource.access$200(WebResource.Java:74)
    at com.Sun.jersey.api.client.WebResource$Builder.get(WebResource.Java:509)

それを少し検索してみたところ、そのURLから証明書を取得し、jdk/lib/securityフォルダーに追加する必要があることがわかりました。しかし、私はどのように進めるかわかりません。

Opensslを使用すると、以下の出力が得られます。

user>openssl s_client -connect  abc.com:443

CONNECTED(00000214)
7832:error:14077438:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert internal error:s23_clnt.c:802:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 308 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : 0000
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1531657560
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
4
J. Doe

これらは、プログラムを機能させるための手順です。ところで、私はグーグルクロームを使用して、ウィンドウズにいます。

証明書は必要です。

1)まず、URLに移動し(WebサイトであるかRESTfulサービスであるかは関係ありません)、google.comを選択しましょう。ページを右クリックして、「検査」をクリックします。

enter image description here

2)[セキュリティ]タブに移動します。

enter image description here

3)そこに着いたら、「証明書の表示」をクリックします。 enter image description here

サイトの証明書の詳細を示すウィンドウがポップアップ表示されます。

4)「認証パス」タブに移動します。そして、階層から必要な証明書をダブルクリックします。 enter image description here

新しいウィンドウがポップアップ表示されます。

enter image description here

この場合、「Googleトラストサービス...」というルート証明書を選択しましたが、「Google InternetAuthorityG3」などのより具体的な証明書を選択することもできます。具体的であればあるほど、セキュリティが強化されると思います(ただし、よくわかりません)。

5)[詳細]タブに移動し、証明書の名前を選択します。

enter image description here

6)[ファイルにコピー]をクリックし、名前と保存場所を選択します。デスクトップに保存して「test.cer」という名前を付けました。

これで、証明書のエクスポートが完了しました。次に、それをjvmのトラストストアに追加します。

1)アプリケーションが実行されているJREを検索します。たとえば、コンピューターにJREが1つしかない(JDKにバンドルされているJREを除く)。それはここにあります:

enter image description here

証明書を格納するターゲットファイルはcacertsです。

enter image description here

2)管理者としてcmdを開き、cd "C:\Program Files\Java\jre-10.0.1\lib\security"(私の場合はcacertsへのパス)を実行します。

3)次のコマンドを発行します。

keytool -import -storepass changeit -noprompt -alias *alias* -keystore cacerts -trustcacerts -file *path_to_certificate*

エイリアスは、ファイルの名前に関係なく、トラストストアにすでに存在する他の証明書のエイリアスと衝突しない限り、何でもかまいません。

私の場合、私はこれを発行します:

enter image description here

4)これで、次のコマンドを発行できます:keytool -list -keystore cacerts -alias *alias*証明書が追加されたことを確認するには、このコマンドを発行すると、パスワードの入力を求められます。ステップ3で、私があなたに与えたコマンドには次のオプションがありました:-storepass changeit、それであなたのパスワードはchangeitになります。

enter image description here

私の場合、すべてが大丈夫です。

5)これで、アプリケーションを再起動でき、動作するはずです。コンピュータを再起動することを勧める人もいますが、それが必要かどうかはわかりません。

4
Coder-Man

おとこ!上記のどれも必要ありません!!! RestApiコードの前にRestAssured.useRelaxedHTTPSValidation();を渡すだけです。完了! `

0
Jason Backer