1

clientAuth=true で自己署名証明書を使用して Tomcat6 を構成し、HttpClient 4.1.x を使用してクライアント側で Tomcat サーバーを呼び出そうとしています。

http://virgo47.wordpress.com/2010/08/23/tomcat-web-application-with-ssl-client-certificates/に記載されている指示に従いました。ブラウザまたはopensslクライアントから(コマンド「openssl s_client -cert client.crt -key client.key -CAfile ca.crt -connect localhost:8443」を実行しました)。

私が直面している問題は、HttpClient にあります。HttpClient を作成するために次のコードを書きました

    private DefaultHttpClient creatHttpClient(KeyStore keyStore, 
        char[] keyStorePassword, KeyStore trustStore, char[] trustStorePassword) {
    try {

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(trustStore); // This contains CA certs
        TrustManager[] tm = trustManagerFactory.getTrustManagers();

        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, keyStorePassword); // This contain client private key
        KeyManager[] km = keyManagerFactory.getKeyManagers();

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(km, tm, new SecureRandom());

        SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslContext, 
                SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        HttpParams params = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(params, 10000);
        HttpConnectionParams.setSoTimeout(params, 30000);

        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme("https", 
                443, sslSocketFactory));

        ClientConnectionManager clientConnectionManager = 
                new ThreadSafeClientConnManager(schemeRegistry);

        final DefaultHttpClient httpClient = new DefaultHttpClient(
                clientConnectionManager, params);
        return httpClient;
    } catch(Exception e) {
        throw e;
    }
}

このために、私は受け取った

    javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

デバッグを有効にしました

    static
    { System.setProperty("javax.net.debug", "ssl,handshake,trustmanager"); }

次のデバッグ ログを受け取りました

    main, handling exception: java.lang.RuntimeException: Unexpected error:                      java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
    main, SEND TLSv1 ALERT:  fatal, description = internal_error 
    main, WRITE: TLSv1 Alert, length = 2
    main, called closeSocket()
    main, IOException in getSession():  javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
    main, called close()
    main, called closeInternal(true)
    main, called close()
    main, called closeInternal(true)

この場合、何が問題になる可能性がありますか? ssl証明書エラーを無視したくないのではなく、適切に認証したい.

4

1 に答える 1

0

私は自分の問題を解決しました。問題は、キーストアとトラストストアを使用してロードしていたことです

InputStream ksin = this.getClass().getResourceAsStream("client.jks");
InputStream tsin = this.getClass().getResourceAsStream("cacerts.jks");

& は Junit テストでこれらの行を使用していました & .jks ファイルを見つけることができませんでした。

私はこれを次のように置くことで理解しました

if(0 == keyStore.size()) { throw new RuntimeException("Keystore is empty"); }
if(0 == trustStore.size()) { throw new RuntimeException("Truststore is empty"); }

キーストアとトラストストアの初期化後。

だから、私は行を次のように変更しました

InputStream ksin = Thread.currentThread().getContextClassLoader().getResourceAsStream("client.jks");
InputStream tsin = Thread.currentThread().getContextClassLoader().getResourceAsStream("cacerts.jks");

&すべてがうまくいきました。

于 2013-03-02T08:31:48.020 に答える