2013-10-17 15 views
9

私たちがホストしているSSL Webサービスに接続しているAndroidアプリケーションがあります。 WebサーバーはApacheであり、作成した独自のCAと自己署名入りのSSL証明書を持っています。自己署名証明書とCAを使用したAndroid SSL HTTPリクエスト

セキュリティの[ユーザー信頼証明書]セクションでAndroidタブレットにCA証明書をインポートしました。ここで私は、Webサーバーへのアクセスをテストしているし、有効なものとして、Webサービスの証明書を示していることを確認することができ

(下のスクリーンショット)

Valid certificate

は、セキュリティ設定の証明書です:

Trusted certificate

私のアプリケーションでWebサービスにアクセスしようとすると、「ピア証明書がない」例外が発生します。

これは簡略化されたSSLの実装です:

public class MainActivity extends Activity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    // allows network on main thread (temp hack) 
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
    StrictMode.setThreadPolicy(policy); 

    SchemeRegistry schemeRegistry = new SchemeRegistry(); 
    //schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); 
    schemeRegistry.register(new Scheme("https", newSSLSocketFactory(), 443)); 


    HttpParams params = new BasicHttpParams(); 

    SingleClientConnManager mgr = new SingleClientConnManager(params, schemeRegistry); 

    HttpClient client = new DefaultHttpClient(mgr, params); 

    HttpPost httpRequest = new HttpPost("https://our-web-service.com"); 

    try { 
     client.execute(httpRequest); 
    } catch (Exception e) { 
     e.printStackTrace(); // 
    } 
} 

/* 
* Standard SSL CA Store Setup // 
*/ 
private SSLSocketFactory newSSLSocketFactory() { 

    KeyStore trusted; 

    try { 
     trusted = KeyStore.getInstance("AndroidCAStore"); 
     trusted.load(null, null); 
     Enumeration<String> aliases = trusted.aliases(); 

     while (aliases.hasMoreElements()) { 
      String alias = aliases.nextElement(); 
      X509Certificate cert = (X509Certificate) trusted.getCertificate(alias); 
      Log.d("", "Alias="+alias); 
      Log.d("", "Subject DN: " + cert.getSubjectDN().getName()); 
      Log.d("", "Issuer DN: " + cert.getIssuerDN().getName()); 
     }  

     SSLSocketFactory sf = new SSLSocketFactory(trusted); 
     sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER); 

     return sf; 

    } catch (Exception e) { 
     // TODO Auto-generated catch block 
     throw new AssertionError(e); 
    } 
} 

} 

whileループだけで、証明書を出してくれると私はログに自分のCAを見ることができます。しかし、私はまだ "ピア証明書なし"の例外を取得します。

10-17 18:29:01.234:I /をSystem.out(4006):いいえピア証明書

私は手動でこの実装で何とか自分のCA証明書をロードする必要がありますか?

使用することによって解決
+0

を、あなたは、この実装では、あなたのCA証明書をロードし、手動で試したことがありますか? – BON

+0

http://www.startssl.com/からドメインの無料の&信頼できるSSL証明書を取得できます(一部のアプリで使用しています)。すべての端末でCAを追加する必要はありませんあなたのアプリを使いたい –

答えて

4

:HttpsURLConnectionの

URLConnection conn = null; 
URL url = new URL(strURL); 
conn = url.openConnection(); 
HttpsURLConnection httpsConn = (HttpsURLConnection) conn; 

これは、ユーザがインストールしたCA証明書を使用して正常に動作するようです。

2

あなたはにhere is suggestedにもかかわらず、またDefaultHttpClientを使用してタスクを達成することができます:あなたが持っているかもしれないので、インポートしたり、アプリケーションに証明書を追加することでも

新しいコード

ご注意のためのHttpURLConnectionを優先証明書が期限切れになったときに証明書を更新する際の問題。

はここDefaultHttpClientが自己署名証明書の信頼を取得する方法:HttpsURLConnectionを取得する方法を

* This method returns the appropriate HttpClient. 
* @param isTLS Whether Transport Layer Security is required. 
* @param trustStoreInputStream The InputStream generated from the BKS keystore. 
* @param trustStorePsw The password related to the keystore. 
* @return The DefaultHttpClient object used to invoke execute(request) method. 
private DefaultHttpClient getHttpClient(boolean isTLS, InputStream trustStoreInputStream, String trustStorePsw) 
    throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException, UnrecoverableKeyException { 
    DefaultHttpClient client = null;   
    SchemeRegistry schemeRegistry = new SchemeRegistry(); 
    Scheme http = new Scheme("http", PlainSocketFactory.getSocketFactory(), 8080); 
    schemeRegistry.register(http); 
    if(isTLS) { 
     KeyStore trustKeyStore = null; 
     char[] trustStorePswCharArray = null; 
     if(trustStorePsw!=null) { 
      trustStorePswCharArray = trustStorePsw.toCharArray(); 
     } 
     trustKeyStore = KeyStore.getInstance("BKS"); 
     trustKeyStore.load(trustStoreInputStream, trustStorePswCharArray); 
     SSLSocketFactory sslSocketFactory = null; 
     sslSocketFactory = new SSLSocketFactory(trustKeyStore); 
     Scheme https = new Scheme("https", sslSocketFactory, 8443); 
     schemeRegistry.register(https); 
    }     
    HttpParams httpParams = new BasicHttpParams(); 
    HttpConnectionParams.setConnectionTimeout(httpParams, CONNECTION_TIMEOUT); 
    HttpConnectionParams.setSoTimeout(httpParams, SOCKET_TIMEOUT);   
    ClientConnectionManager clientConnectionManager = new ThreadSafeClientConnManager(httpParams, schemeRegistry);   
    client = new DefaultHttpClient(clientConnectionManager, httpParams);   
    return client; 
} 

、ここで:

* This method set the certificate for the HttpsURLConnection 
* @param url The url to contact. 
* @param certificateInputStream The InputStream generated from the .crt certificate. 
* @param certAlias The alias for the certificate. 
* @return The returned HttpsURLConnection 
private HttpsURLConnection getHttpsURLConnection(URL url, InputStream certificateInputStream, String certAlias) 
    throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException { 
    HttpsURLConnection connection = null; 
    CertificateFactory certFactory = null; 
    Certificate cert = null; 
    KeyStore keyStore = null; 
    TrustManagerFactory tmFactory = null; 
    SSLContext sslContext = null; 
    // Load certificates from an InputStream 
    certFactory = CertificateFactory.getInstance("X.509"); 
    cert = certFactory.generateCertificate(certificateInputStream); 
    certificateInputStream.close(); 
    // Create a KeyStore containing the trusted certificates 
    keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
    keyStore.load(null, null); 
    keyStore.setCertificateEntry(certAlias, cert); 
    // Create a TrustManager that trusts the certificates in our KeyStore 
    tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
    tmFactory.init(keyStore); 
    // Create an SSLContext that uses our TrustManager 
    sslContext = SSLContext.getInstance("TLS"); 
    sslContext.init(null, tmFactory.getTrustManagers(), null); 
    connection = (HttpsURLConnection)url.openConnection(); 
    connection.setSSLSocketFactory(sslContext.getSocketFactory()); 
    return connection; 
}