当前位置: 首页 > 知识库问答 >
问题:

HttpClient失败与握手失败在Android 5.0Lollipop

姬阳曜
2023-03-14

在Android 5.0LollipopDefaultHttpClient似乎被打破。它不能设置连接到一些网站,成功地设置了以前版本的Android.

例如,我尝试连接到https://uralsg.megafon.ru

//Create httpclient like in https://stackoverflow.com/questions/18523784/ssl-tls-protocols-and-cipher-suites-with-the-androidhttpclient
HttpClient client = new DefaultHttpClient(manager, params);
HttpGet httpGet = new HttpGet("https://uralsg.megafon.ru");
HttpResponse client = httpclient.execute(httpGet);

此代码在Android 2.3-4.4中工作,但在Android 5.0(设备和模拟器)上失败,错误连接被对等方关闭。当然,这是可以理解的,因为Android 5.0试图将这台旧服务器与TLSv1连接起来。2和现代密码,它不支持它们。

好的,使用AndroidHttpClient的SSL/TLS协议和密码套件中的示例代码,我们将协议和密码限制为TLSv1和SSL_RSA_以及_RC4_128_MD5。现在它失败了,出现了另一个错误:

javax.net.ssl.SSLHandshakeException: Handshake failed
caused by 
    error:140943FC:SSL routines:SSL3_READ_BYTES:sslv3 alert bad record mac 
    (external/openssl/ssl/s3_pkt.c:1286 0x7f74c1ef16e0:0x00000003) 
    at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake

当然,这段代码在Android 2.3-4.4上运行平稳。

我用wireshark检查了流量:

302 4002.147873000  192.168.156.30  83.149.32.13    TLSv1   138 Client Hello
303 4002.185362000  83.149.32.13    192.168.156.30  TLSv1   133 Server Hello
304 4002.186700000  83.149.32.13    192.168.156.30  TLSv1   1244    Certificate
305 4002.186701000  83.149.32.13    192.168.156.30  TLSv1   63  Server Hello Done
307 4002.188117000  192.168.156.30  83.149.32.13    TLSv1   364 Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
308 4002.240695000  83.149.32.13    192.168.156.30  TLSv1   61  Alert (Level: Fatal, Description: Bad Record MAC)

您可以看到连接已建立,但服务器已发出警报,因为它可能无法解码加密的握手消息。

我没有设法连接到https://uralsg.megafon.ru使用HttpClient在Android 5.0.股票浏览器确实连接它。Android2.3-4.4以任何方式连接这个网站没有任何困难。

有什么方法可以让HttpClient连接这样的网站?这只是一个例子,我相信有很多遗留服务器无法通过Android 5.0和HttpClient连接。

共有2个答案

裘嘉树
2023-03-14

我试着在一家定制的插座工厂里更换密码套件,但没有用。在我的情况下,我必须删除TLSv1。1和TLSv1。来自套接字的EnabledProtocol的2个协议。一些旧服务器似乎不能很好地处理新协议的协议协商。有很多创建自定义套接字工厂的示例,例如如何在使用HttpsURLConnection时覆盖Android发送到服务器的密码列表?,还有其他的Apache套接字。完成后,我调用了下面的AdjustSocket方法来删除协议。

private void AdjustSocket(Socket socket)
{
    String[] protocols = ((SSLSocket) socket).getSSLParameters().getProtocols();
    ArrayList<String> protocolList = new ArrayList<String>(Arrays.asList(protocols));

    for (int ii = protocolList.size() - 1; ii >= 0; --ii )
        {
        if ((protocolList.get(ii).contains("TLSv1.1")) || (protocolList.get(ii).contains("TLSv1.2")))
            protocolList.remove(ii);
        }

    protocols = protocolList.toArray(new String[protocolList.size()]);
    ((SSLSocket)socket).setEnabledProtocols(protocols);
}
禄豪
2023-03-14

更新:这是后端的一个bug,而不是Android5,尽管密码确实有问题。

我也有同样的问题。对我来说,结果是密码TLS_DHE_RSA_与_AES_256_GCM_SHA384,它是从Android5(更新的)默认密码集中选择的。

当我把它从可接受密码的客户端列表中删除后,连接又开始工作了。

android 5更改日志提到:

  • AES-GCM(AEAD)密码套件现已启用

我很确定这就是罪魁祸首。一旦TLS_DHE_RSA_WITH_AES_256_GCM_SHA384是首选(由服务器),连接将失败。

请注意,TLS\u DHE\u RSA\u和\u AES\u 128\u GCM\u SHA256可以工作。

我猜要么是Android实现的TLS\u DHE\u RSA\u和\u AES\u 256\u GCM\u SHA384有问题,要么是你正在与之交谈的服务器有问题。

解决:

  1. 从服务器上的可用密码中删除TLS\u DHE\u RSA\u WITH_AES\u 256\u GCM\u SHA384(无需重新部署应用程序

通过实现自己的SSLSocketFactory并调用

sslSocket.setEnabledCipherSuites(String[] suites);

关于SSLSocket创建。

编辑:请注意,这不一定是android错误,可能是服务器实现有问题。如果您的问题确实是由密码引起的,请在android bug tracker上留言](https://code.google.com/p/android/issues/detail?id=81603)1.谢谢!

 类似资料:
  • 我正在学习SSL通信,我遇到了这个问题。我正在编写一个简单的客户端,它试图与本地apache服务器握手。服务器启用https。我将服务器证书添加到所有可能的信任存储(jdk中的一个 注意:我从以下教程中获取了代码: http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#KRB 停留

  • 我通过受ssl v3保护的cxf使用soap服务。我从服务器下载.cer文件,并通过keytool使用以下指令创建JKS文件: 在java代码中,我将此代码用于客户端配置: 对于调用此代码的服务: 当我运行代码时,会发生此错误: 我搜索此错误,我意识到该错误是针对不良信任存储的。但我不知道如何生成正确的信任库。

  • 我在使用硒测试时收到此错误 我现在的代码是 是否有其他方法可以忽略/解决此错误?

  • 我正在对我们的数据库服务进行超文本传输协议请求的大循环。一切都很好,但是每当我运行它时,在成功查询(看似随机)数量后,我都会收到以下错误:

  • 问题内容: 我正在尝试将Jenkins CI配置为对我们的项目执行持续集成,并且无法使其通过https连接到我们的SVN存储库。每当我尝试配置存储库URL并尝试连接时,都会遇到以下异常: 我在tomcat实例上启用了SSL调试(使用),并得到了以下信息: 我尝试按照这篇文章中的说明在tomcat中添加属性,但仍然出现相同的错误。 在这一点上,我对发生的事情完全感到困惑。不幸的是,我不是完全了解SS

  • 问题内容: 我已经将证书导入到信任库中,但是仍然无法成功连接到该URL。我已经尝试了所有方法,任何人都可以看到输出并提供帮助吗? 无法弄清楚这是什么,应用程序正在使用java1.6,但是SSLPoke无法通过两种情况 问题答案: 我发现客户也进行了验证。因此它是2路身份验证。客户还必须将我的公共证书导入其密钥库。