2016-03-14 115 views
1

我在写与服务器交互的android应用程序。在我的应用程序中,我有几个类扩展了AsyncTask - 一个请求的类。每个类都有URL和HttpURLConnection实例。服务器地址是:https:/myaddress.com(错过了一个'/')。我把它放在应用程序字符串资源中。我在我的类中使用的URL如下所示:https:/myaddress.com/query1,https:/myaddres.com/query2 ... 现在我需要使用Https,并且在用户开始交互之前,我需要信任CA 。 第一个用户的请求是认证(类登录)。 如果我把下面的代码到登录类Android HttpsURLConnection信任证书

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
String algorithm = TrustManagerFactory.getDefaultAlgorithm(); 
TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); 
tmf.init(keyStore); 

SSLContext context = SSLContext.getInstance("TLS"); 
context.init(null, tmf.getTrustManagers(), null); 

URL url = new URL("https://myaddress.com/"); 
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); 
urlConnection.setSSLSocketFactory(context.getSocketFactory()); 
urlConnection.setRequestProperty("KeepAlive", true); 
InputStream in = urlConnection.getInputStream(); 
//posting content and handling response 
finally { 
    in.close(); 
    urlConnection.disconnect(); 
} 

是否足够信任CA? 我可以确定其他类中的其他HttpsURLConnection实例将使用安全连接吗? 根据文档,我必须使用一个HttpsURLConnection实例来处理一个请求,但它可以使用相同的底层Socket来处理多个请求/响应对。我的代码真的吗?或者我不需要调用disconnect()?

回答

0

我不认为它会以这种方式工作(除非您的证书由本机可信CA提供,但您不需要实例化新的TrustManager)。

下面是我们使用的是在我们的应用程序:

private static TrustManager[] getTrustManagers(Context context) throws KeyStoreException, NoSuchAlgorithmException, CertificateException 
    { 
    try 
    { 
     // Create a KeyStore containing our trusted CAs 
     String keyStoreType = KeyStore.getDefaultType(); 
     KeyStore keyStore = KeyStore.getInstance(keyStoreType); 
     keyStore.load(null, null); 

     AssetManager assetManager = context.getAssets(); 

     for (String file : assetManager.list("")) 
     { 
     if (file.endsWith(".crt")) 
     { 
      CertificateFactory cf = CertificateFactory.getInstance("X509"); 
      InputStream caInput = new BufferedInputStream(assetManager.open(file)); 
      Certificate ca; 
      try 
      { 
      ca = cf.generateCertificate(caInput); 
      Log.info(TAG, "CA certificate [" + ((X509Certificate) ca).getSubjectDN() + "] added to truststore."); 
      } 
      finally 
      { 
      caInput.close(); 
      } 
      keyStore.setCertificateEntry(file, ca); 
     } 
     } 

     // Create a TrustManager that trusts the CAs in our KeyStore 
     String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); 
     TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); 
     tmf.init(keyStore); 
     return tmf.getTrustManagers(); 
    } 
    catch (IOException e) 
    { 
     // TODO 
     return null; 
    } 
    } 

我们捆绑的根CA证书的公钥。

我可以肯定,其他类中的其他HttpsURLConnection实例将使用安全连接吗?

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); 

然后,所有新HttpsURLConnection将使用此SocketFactory

这是真的我的代码?或者我不需要调用disconnect()?

每次你需要做一个请求时,只要做一个新的HttpsURLConnection。将由HttpsURLConnection使用的底层SocketFactory将为您处理套接字。 如果您需要在10/20秒内多次拨打相同的URL,那么请勿disconnect,但在一般情况下,您需要拨打disconnect以释放所有底层资源。

+0

谢谢! 如果我的地址具有由本机可信CA签名的证书,则只能使用SSLContext和SSLSocketFactory而不使用TrustManager和KeyStore。当其他人需要创建密钥库时,使用* .crt文件生成证书,将其加载到我的密钥库中,然后使用TrustManager。这样对吗? – user3533397

+0

@ user3533397如果您的证书由本机可信CA签名,那么您不需要调用'context.init'。这已经是使用的默认'TrustManager'了。如果您使用不受信任的证书,则需要更改'SSLContext'。请注意,在我们的项目中,我们有由Comodo签名的证书,但由于服务器端配置错误的CA证书链,我们需要使用自定义TrustManager。 – neomega

+0

如果我们有原生的可信CA,那么我们只能使用'HttpsURLConnection urlConnection =(HttpsURLConnection)url.openConnection();',而不需要'SSLSocketFactory'? – user3533397