Android:使用HttpsURLConnection的HTTPS(SSL)连接

我有2个应用程序,一个是Servlet / Tomcat服务器,另一个是Android应用程序。

我想使用HttpURLConnection在两者之间发送和接收XML。

码:

private String sendPostRequest(String requeststring) { DataInputStream dis = null; StringBuffer messagebuffer = new StringBuffer(); HttpURLConnection urlConnection = null; try { URL url = new URL(this.getServerURL()); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setDoOutput(true); urlConnection.setRequestMethod("POST"); OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream()); out.write(requeststring.getBytes()); out.flush(); InputStream in = new BufferedInputStream(urlConnection.getInputStream()); dis = new DataInputStream(in); int ch; long len = urlConnection.getContentLength(); if (len != -1) { for (int i = 0; i < len; i++) if ((ch = dis.read()) != -1) { messagebuffer.append((char) ch); } } else { while ((ch = dis.read()) != -1) messagebuffer.append((char) ch); } dis.close(); } catch (Exception e) { e.printStackTrace(); } finally { urlConnection.disconnect(); } return messagebuffer.toString(); } 

现在,我需要使用SSL来发送XML以确保安全性。

首先,我使用Java Keytool生成.keystore文件。

 Keytool -keygen -alias tomcat -keyalg RSA 

然后我将XML代码放在Tomcat的server.xml文件中以使用SSL

  

然后,我将它更改为HttpsURLConnection的HttpURLConnection

  private String sendPostRequest(String requeststring) { DataInputStream dis = null; StringBuffer messagebuffer = new StringBuffer(); HttpURLConnection urlConnection = null; //Conexion por HTTPS HttpsURLConnection urlHttpsConnection = null; try { URL url = new URL(this.getServerURL()); //urlConnection = (HttpURLConnection) url.openConnection(); //Si necesito usar HTTPS if (url.getProtocol().toLowerCase().equals("https")) { trustAllHosts(); //Creo la Conexion urlHttpsConnection = (HttpsURLConnection) url.openConnection(); //Seteo la verificacion para que NO verifique nada!! urlHttpsConnection.setHostnameVerifier(DO_NOT_VERIFY); //Asigno a la otra variable para usar simpre la mism urlConnection = urlHttpsConnection; } else { urlConnection = (HttpURLConnection) url.openConnection(); } //Do the same like up 

并添加一个trustAllHosts方法来信任每个服务器(不检查任何证书)

 private static void trustAllHosts() { X509TrustManager easyTrustManager = new X509TrustManager() { public void checkClientTrusted( X509Certificate[] chain, String authType) throws CertificateException { // Oh, I am easy! } public void checkServerTrusted( X509Certificate[] chain, String authType) throws CertificateException { // Oh, I am easy! } public X509Certificate[] getAcceptedIssuers() { return null; } }; // Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[] {easyTrustManager}; // Install the all-trusting trust manager try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (Exception e) { e.printStackTrace(); } } 

这些变化非常好,但我不想相信每个服务器。 我想使用我的密钥库文件来validation连接并以正确的方式使用SSL。 我在互联网上阅读了很多并做了很多测试,但我不明白我该做什么以及如何做。

有人能帮助我吗?

非常感谢你

抱歉我的英语不好

————————-更新2011/08/24 ——————- ——————————

好吧,我还在努力。 我创建了一个新方法来设置KeyStore,InputStream等

该方法如下所示:

 private static void trustIFNetServer() { try { TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); KeyStore ks = KeyStore.getInstance("BKS"); InputStream in = context.getResources().openRawResource(R.raw.mykeystore); String keyPassword = "password"; ks.load(in, keyPassword.toCharArray()); in.close(); tmf.init(ks); TrustManager[] tms = tmf.getTrustManagers(); SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, tms, new java.security.SecureRandom()); } catch (Exception e) { e.printStackTrace(); } } 

首先,我在密钥和证书方面遇到了很多问题,但现在它正在运行(我想是这样)

我现在的问题是TimeOutexception。 我不知道它为什么会产生。 我认为这是数据写入的东西,但我还不能解决。

任何想法?

您需要为自签名证书创建信任库文件,如此处所述。 在客户端使用它来连接您的服务器。 如果你使用JKS或其他格式并不重要,我现在就假设JKS。

为了实现您的想法,显然您需要一个不同的TrustManager 。 您可以使用TrustManagerFactory并将其信任设置提供给新创建的信任库。

 TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); KeyStore ks = KeyStore.getInstance("JKS"); FileInputStream in = new FileInputStream(""); ks.load(in, "password".toCharArray()); in.close(); tmf.init(ks); TrustManager[] tms = tmf.getTrustManagers(); 

使用tms初始化SSLContext而不是将新的信任设置用于SSL / TLS连接。

此外,您应确保服务器TLS证书的CN部分等于服务器的FQDN(完全限定的域名),例如,如果您的服务器基本URL是“ https://www.example.com ”,那么证书的CN应为“www.example.com”。 这是主机名validation所必需的,这是一种可以防止中间人攻击的function。 你可以禁用它,但只有在使用它时你的连接才会非常安全。

创建您的信任存储,作为资产存储并使用它初始化此SocketFactory 。 然后使用工厂而不是你自己的“信任每个人”。

如果要忽略所有证书,请忽略握手,然后这样做: HttpsURLConnection和间歇性连接