2011-03-28 125 views
7

我目前正在爲Android(2.2)和使用SSL的服務器編寫客戶端部分。我設法在服務器和普通客戶端之間交換消息,但Android似乎對自簽名證書不太滿意。 我已經搜索過Stackoverflow和谷歌搜索很多人都有類似的問題。到目前爲止,我發現的所有答案要麼不起作用,要麼沒有任何意義。大多數代碼示例都是針對HTTPS的,但是我無法使用,因爲我需要通過套接字進行通信(SSLSocket是我最好的猜測)。我已經嘗試了很多不同的代碼,但現在我又回到了零。Android上的SSL客戶端

到目前爲止,我已經發現我必須創建一個證書(我認爲是正確的)和一個自定義的TrustManager。很明顯,我一直沒有找到任何工作代碼,這就是爲什麼我在這裏問,因爲通常有一些真正有幫助的人。

我正在尋找應該做什麼以及一些代碼的詳細說明,這些代碼可以變成一個可用的Android客戶端代碼。

在此先感謝

回答

1

我已經做了它與移植原生android瀏覽器。 我剛剛更改了如何創建ssl上下文。 我答應,我也將提上SandroB網站的一些工作的例子,但... :)

https://market.android.com/details?id=org.sandrob

http://code.google.com/p/sandrob/source/browse/misc/examples/HttpsConnection.java

+0

感謝您的回覆。我查看了你鏈接的代碼,看起來很有趣。問題在於它使用了很多類,這似乎是自定義的。我在Google上查找了一些它們,發現它們已經在其他圖書館中實施。讓我們看看CertificateChainValidator似乎應該在包android.net.http中 - 但它不在那裏。 是否有一個簡化的完整工作示例,使用標準庫? – Casper 2011-03-29 11:06:26

1

CertificateChainValidator是安卓來源的一部分。 至少在版本/標籤2.2.1_r1

要使其工作,您可以從android源代碼構建瀏覽器,並更改在HttpsConnection.java文件中如何初始化 SSLContext。

你需要keyManagers(與cerfile /密碼初始化)和trustManagers(信任所有)。

sslContext.engineInit(keyManagers,trustManagers,null,cache,null);

+1

嗨。我似乎無法導入,並根據http://developer.android.com/reference/android/net/http/package-summary.html功能似乎並不存在。 據我知道我必須創建海關經理來處理證書,但我還沒有找到工作的一些代碼。順便說一句,我正在使用Android 2.2(API 8)。 – Casper 2011-03-29 16:34:23

1
public class MySSLSocketFactory extends SSLSocketFactory { 
    SSLContext sslContext = SSLContext.getInstance("TLS"); 

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

     TrustManager tm = new X509TrustManager() { 
      public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
      } 

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

      public X509Certificate[] getAcceptedIssuers() { 
       return null; 
      } 
     }; 

     sslContext.init(null, new TrustManager[] { tm }, null); 
    } 

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

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

你HttpClient的是

public HttpClient getNewHttpClient() { 
     try { 
      KeyStore trustStore = KeyStore.getInstance(KeyStore 
        .getDefaultType()); 
      trustStore.load(null, null); 

      SSLSocketFactory sf = new MySSLSocketFactory(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); 

      return new DefaultHttpClient(ccm, params); 
     } catch (Exception e) { 
      return new DefaultHttpClient(); 
     } 
    } 

希望它可以幫助你。