1. ホーム
  2. java

[解決済み] java.security.cert.CertificateException を修正する方法。No subject alternative names present" エラーを修正する方法は?

2022-02-05 05:36:40

質問内容

私は、HTTPS経由でウェブサービスを消費するJavaウェブサービスクライアントを使用しています。

import javax.xml.ws.Service;

@WebServiceClient(name = "ISomeService", targetNamespace = "http://tempuri.org/", wsdlLocation = "...")
public class ISomeService
    extends Service
{

    public ISomeService() {
        super(__getWsdlLocation(), ISOMESERVICE_QNAME);
    }

サービスURLに接続すると( https://AAA.BBB.CCC.DDD:9443/ISomeService ) の例外が発生します。 java.security.cert.CertificateException: No subject alternative names present .

これを修正するために、私はまず openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt を実行すると、次のような内容がファイルに表示されます。 certs.txt :

CONNECTED(00000003)
---
Certificate chain
 0 s:/CN=someSubdomain.someorganisation.com
   i:/CN=someSubdomain.someorganisation.com
-----BEGIN CERTIFICATE-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=someSubdomain.someorganisation.com
issuer=/CN=someSubdomain.someorganisation.com
---
No client certificate CA names sent
---
SSL handshake has read 489 bytes and written 236 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-MD5
Server public key is 512 bit
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : RC4-MD5            
    Session-ID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    Session-ID-ctx:                 
    Master-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    Key-Arg   : None
    Start Time: 1382521838
    Timeout   : 300 (sec)
    Verify return code: 21 (unable to verify the first certificate)
---

AFAIK、今私は必要なのは

  1. の部分を抽出し certs.txt との間に -----BEGIN CERTIFICATE----------END CERTIFICATE----- ,
  2. と同じになるように修正します。 AAA.BBB.CCC.DDD
  3. を使用し、その結果をインポートします。 keytool -importcert -file fileWithModifiedCertificate (ここで fileWithModifiedCertificate は操作1と2の結果である)。

これでよいのでしょうか?

もしそうなら、ステップ1の証明書をIPベースのアドレスで動作させるには、具体的にどうすればよいのでしょうか( AAA.BBB.CCC.DDD ) ?

更新1 (2013.10.23 15:37 MSK)。 への回答で 類似質問 は、次のように読みました。

そのサーバーを管理していない場合は、そのサーバーのホスト名を使用します。 少なくとも既存のホスト名に一致するCNがあること。 の証明書)。

use"とは、具体的にどのような意味ですか?

どのように解決するのですか?

HTTPSのチェックを無効にすることで、この問題を解決しました。 こちら :

には、以下のコードを記述しました。 ISomeService クラスがあります。

static {
    disableSslVerification();
}

private static void disableSslVerification() {
    try
    {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        }
        };

        // Install the all-trusting trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        // Create all-trusting host name verifier
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        // Install the all-trusting host verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }
}

を使っているので https://AAA.BBB.CCC.DDD:9443/ISomeService はテスト用なので、十分な解決策ですが、本番ではこの方法をとらないようにしてください。

一度に1つの接続に対してSSLを無効化することもできます。

 // don't call disableSslVerification but use its internal code:
 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 if (conn instanceof HttpsURLConnection) {
    HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
    httpsConn.setHostnameVerifier(allHostsValid);
    httpsConn.setSSLSocketFactory(sc.getSocketFactory());
 }