不受信任的证书错误和Android上的httpclient

5

我正在使用Apache HttpClient库来建立https连接。不幸的是,Android给我返回了一个“不受信任的服务器证书”错误。如果我使用手机浏览器浏览该网站,则可以正确验证证书,这使我相信我需要让HttpClient了解手机上的根证书。以下是我的HttpClient设置代码:

HttpParams params = new BasicHttpParams();

HttpConnectionParams.setConnectionTimeout( params, 20000 );
HttpConnectionParams.setSoTimeout( params, 20000 );

HttpProtocolParams.setVersion( params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset( params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue( params, false);

SchemeRegistry schReg = new SchemeRegistry();
schReg.register( new Scheme( "http", PlainSocketFactory.getSocketFactory(), 80 ) );
schReg.register( new Scheme( "https", SSLSocketFactory.getSocketFactory(), 443 ) );

ClientConnectionManager conMgr = new ThreadSafeClientConnManager( params, schReg );

DefaultHttpClient defaultHttpClient = new DefaultHttpClient( conMgr, params );

return ( defaultHttpClient );

您可以看到,我对SSLSocketFactory没有做任何特殊处理。如何使HttpClient库在不添加自定义证书到密钥库的情况下验证我的站点?我应该创建一个自定义的SSLSocketFactory并从Android手机加载cacerts.bks吗?在这种情况下,我可能会遇到不同手机上密钥库密码不同的问题?

如果您需要更多信息,请告诉我。这个SSL的东西对我来说相当困难。


我使用HttpClient访问HTTPS没有任何问题。我只是在使用BasicHttpParams和DefaultHttpClient,没有使用ClientConnectionManager或SchemeRegistry...你认为这些对你来说是必要的吗? - SteelBytes
https://dev59.com/UHNA5IYBdhLWcg3wWseK - Peter Knego
证书需要进行验证。安装“无检查”TrustManager并不是首选,否则使用ssl的意义何在?我想确保我连接到正确的主机,并且证书没有被篡改。感谢提供链接。 - Ivo
经过一周长时间查看博客、Java代码和Android源代码,结果发现问题在我连接的网站上SSL证书的排序上。因此,如果遇到证书验证问题,一定要仔细检查证书是否按正确顺序呈现,并且根证书是否存在于Android设备上! - Ivo
3个回答

3
我相信您的证书不包含验证到系统受信任根证书路径所需的所有中间证书。这可能会被某些SSL配置验证工具报告为“不完整的证书链”。
证书可以包含一个特殊的“颁发者信息访问”扩展(RFC-3280),其中包含指向颁发者证书的URL。大多数浏览器可以使用AIA扩展来下载缺失的中间证书以完成证书链。但是一些客户端(移动浏览器,OpenSSL)不支持此扩展,因此将此类证书报告为不受信任。
您可以通过手动连接证书到受信任的根证书(按顺序排列,不包括受信任的根证书),来解决“不完整的证书链”问题。请注意,受信任的根证书不应该在其中,因为它已经包含在系统的根证书存储中。
您应该能够从颁发者那里获取中间证书并自行连接它们。我编写了一个脚本来自动执行此过程,它遍历AIA扩展以生成正确链接证书的输出。 https://github.com/zakjan/cert-chain-resolver

1
感谢您的评论,您的工具最终帮助我解决了一个问题。 - producerism

0

跟进zakjan的回答,我在尝试在安卓webview中使用jquery进行AJAX请求时遇到了问题。它在浏览器中可以工作,但在我的应用程序中无法工作。

我使用了这个网站:https://certificatechain.io/

我粘贴了我从Comodo(positiveSSL)获得的已签名.crt文件的文本,并得到了我需要的所有内容的连接。我将其保存为我的域名+"chain.crt"(见下文)

然后,在我的apache配置中,我为特定的虚拟主机输入了类似于以下内容:

SSLEngine On
SSLCertificateFile /etc/ssl/localcerts/example_com.crt
SSLCertificateKeyFile /etc/ssl/localcerts/example.com.key
SSLCACertificateFile /etc/ssl/localcerts/example.com.chain.crt

之后,我的Android应用程序的Webview在使用ajax向我的服务器POST时没有问题。我在两个真实设备上尝试了它,一个运行2.3.4,另一个运行4.x。并且在运行2.3的模拟器上也可以正常工作。

希望这可以帮到你。


-2

11
不要在生产环境中这样做!你将关闭所有 SSL 保护。这只应该用于内部测试。任何人都可以进行中间人攻击,窃取所有敏感信息。 - Bishnu
1
我想补充一下,现在谷歌拒绝任何试图绕过此步骤的应用程序。 - StevenTB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接