2011-03-28 91 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(); 
     } 
    } 

希望它可以帮助你。