Android使用HTTPS通信
Android使用HTTPS通信首先需要告诉底层的HTTP客户端,对应https的Schema,使用什么端口,进行SSLSocket的通信。
这里以Httpclient为例
|
|
HostnameVerifier有下面几个策略
- ALLOW_ALL_HOSTNAME_VERIFIER 关闭host验证,允许和所有的host简历SSL通信
- BROWSER_COMPATIBLE_HOSTNAME_VERIFIER 和浏览器兼容的验证策略,即通配符能够匹配所有子域名
- StrictHostnameVerifier 严格匹配模式,hostname必须匹配第一个CN或者任何一个subject-alts
为了避免中间人攻击,首先是需要打开host验证,其次打开了host验证后,那么客户端必须能够验证证书的有效性,否则在请求时会报如下错误
|
|
出现上述错误,通常是下面几个原因:
- 签名证书的CA是个未知的CA
- 服务器证书不是由CA签名的,而是自签名的
- 服务器配置缺少中间CA
未知的CA
出现这种情况的原因是签名CA没有被系统所信任。这种情况可以告诉HttpsURLConnection
来信任CA。
下面的例子从InputStream
读取CA证书,用来创建KeyStore
,然后用它来创建和初始化TrustManager
。TrustManager
是系统用来验证从服务器获取证书的。
|
|
NOTE: 这里如果传入的TrustManager
什么都没有做,那么相当于还是没有加密通信,因为它会接受任何的证书,仍可能遭受中间人攻击。
KeyStore
也可以用JDK的keytool工具生成
|
|
需要注意的是,Android默认使用BKS作为KeyStore Type。
下面的Httpclient的例子
|
|
自签名证书
自签名证书以为着服务器担当自己的CA,这个未知的CA类似的,可以把自签名证书作为信任的CA导入TrustManager。
缺少中间CA
- 服务器把证书链安装完整
- 把未知的中间CA作为信任的未知CA导入TrustManager