DefaultHttpClientを使ってSSL通信しようとしていたのだが、掲題のエラーが発生した。
使える情報を集めるのにかなり時間がかかってしまったので、まとめておく。

このエラーは、自己証明書等で証明書に問題がある場合に発生するらしい。
対策は何種類かあるようだが、一番手っ取り早い証明書のエラーをスルーする方法を記載する。
※セキュリティ的にはよろしくないので注意。

まず、SSLSocketFactoryのカスタムクラスを作る。
LowSecuritySSLSocketFactory.java

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.conn.ssl.SSLSocketFactory;

/**
 * 自己証明書エラースルー版SSLSocketFactory
 */
public class LowSecuritySSLSocketFactory extends SSLSocketFactory {
    private SSLContext mSslContext = SSLContext.getInstance("TLS");

    public LowSecuritySSLSocketFactory(KeyStore truststore)
            throws NoSuchAlgorithmException, KeyManagementException,
            KeyStoreException, UnrecoverableKeyException {
        super(truststore);

        TrustManager trustManager = new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            @Override
            public void checkClientTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
            }
        };

        mSslContext.init(null, new TrustManager[] { trustManager }, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port,
            boolean autoClose) throws IOException, UnknownHostException {
        return mSslContext.getSocketFactory().createSocket(socket, host, port,
                autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return mSslContext.getSocketFactory().createSocket();
    }
}

んで、リクエストする所で下記のようにHttpClientを生成する。
(コピペしてきて全然詰めてないので、無駄な処理混ざってるかも。。

KeyStore trustStore = KeyStore.getInstance(KeyStore
        .getDefaultType());
trustStore.load(null, null);

SSLSocketFactory sf = new LowSecuritySSLSocketFactory(
        trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory
        .getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));

ClientConnectionManager ccm = new ThreadSafeClientConnManager(
        params, registry);

DefaultHttpClient client = new DefaultHttpClient(ccm, params);
// あとはclientを使ってリクエスト実行

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Name *
Email *
Website

*