Android应用中的SSL证书验证

Android应用开发中,与Web服务的交互是常见的需求。为了确保数据传输的安全性,通常会使用SSL证书进行加密。本文将介绍如何在Android应用中处理SSL证书验证,包括创建KeyStore、自定义HttpClient以及处理主机验证。

Android支持使用java.net和org.apache包来访问Web服务。选择使用Apache包,因为相较于Java包,它们更加实用且易于使用。

系统要求

为了在Android应用中添加SSL证书,需要使用Bouncy Castle库。这是一个开源的加密库,可以让向Android的KeyStore中添加自定义的SSL证书。

开始之前

每个Android应用都有自己的信任存储库,称为KeyStore。可以在KeyStore中存储自签名的SSL证书,用于Web服务的验证目的。Android信任一些预设的证书,但如果证书不在其中,就需要将其添加到应用的信任存储库中。

创建KeyStore

首先,需要创建一个KeyStore来存储自签名证书。以下是创建KeyStore的步骤:

  1. 下载并解压Bouncy Castle库,并将.jar文件添加到类路径中。
  2. 打开命令行,导航到应用的文件夹,然后输入以下命令:
keytool -import -v -trustcacerts -alias 0 -file mycertificate.crt \ -keystore res/raw/mystore.bks -storetype BKS -provider \ org.bouncycastle.jce.provider.BouncyCastleProvider -storepass mypassword

其中,file参数指向想要添加的证书文件,keystore参数给想要命名的存储库命名,storepass是访问keystore的密码。

执行命令后,将成功生成mystore.bks文件。

创建自定义HttpClient

为了使用创建的存储库,需要创建一个自定义的Apache DefaultHttpClient,它知道如何使用存储库进行HTTPS请求。以下是创建自定义HttpClient的代码示例:

public class MyHttpClient extends DefaultHttpClient { final Context context; public MyHttpClient(Context context) { this.context = context; } @Override protected ClientConnectionManager createClientConnectionManager() { SchemeRegistry registry = new SchemeRegistry(); registry.register("http", PlainSocketFactory.getSocketFactory(), 80); registry.register("https", newSslSocketFactory(), 443); return new SingleClientConnManager(getParams(), registry); } private SSLSocketFactory newSslSocketFactory() { try { KeyStore trusted = KeyStore.getInstance("BKS"); InputStream in = context.getResources().openRawResource(R.raw.mystore); try { trusted.load(in, "mypassword".toCharArray()); } finally { in.close(); } SSLSocketFactory mySslFact = new SslFactory(trusted); mySslFact.setHostNameVerifier(new MyHstNameVerifier()); return mySslFact; } catch (Exception e) { throw new AssertionError(e); } } }

这段代码帮助接受服务器证书,并设置用于验证的证书。可以看到,如何使用-storename参数"BKS"来获取KeyStore实例,从R.raw加载证书文件mystore,并设置在添加到存储库时使用的密码。

复制mystore文件

将生成的mystore.bks文件导入到res/raw文件夹中,以便上述类可以从那里访问它。

处理主机验证

Android只支持通过哪个主机/域名调用Web服务——如果尝试连接到任何其他主机,它会抛出异常。例如,如果应用连接到一个主机,然后出于任何原因尝试连接到另一个主机,Android将不允许这样做。为了允许这样做,需要设置想要允许应用访问的主机名。

public class MyHostVerifier extends org.apache.http.conn.ssl.AbstractVerifier { String[] allowHost = {"my.ultra.com", "your.ultra.com", "ours.ultra.com"}; @Override public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException { // 如果主机是允许的主机之一,则返回,否则抛出异常 for (int i = 0; i < allowHost.length; i++) { if (host.equals(allowHost[i])) return; } throw new SSLException(); } }

取消注释MyHttpClient类中的setHostVerifier,类就准备好处理SSL主机验证了。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485