javax.net.ssl.SSLProtocolException: SSL 握手中止: ssl=0x7fa2258640: SSL 库失败,通常是协议错误

Posted

技术标签:

【中文标题】javax.net.ssl.SSLProtocolException: SSL 握手中止: ssl=0x7fa2258640: SSL 库失败,通常是协议错误【英文标题】:javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x7fa2258640: Failure in SSL library, usually a protocol error 【发布时间】:2018-07-10 09:59:21 【问题描述】:

我正在尝试一个演示 android 应用程序来连接 servlet(本地服务器和 aws 实例),它给出了 Handshake failed 错误。我也尝试过使用 volley 和 http 客户端。相关代码和 logcat 结果如下。目前我正在使用Android 7.1版本和redmi 5A手机进行测试。

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity 

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        execute();
    

    void execute() 
        new Thread(new Runnable() 
            public void run() 
                try 
            URL url = new URL("https://192.168.0.7:9999/WebS/welcome/test");
            URLConnection connection = url.openConnection();

            String inputString = "hello server";
            //inputString = URLEncoder.encode(inputString, "UTF-8");

            Log.d("inputString", inputString);

            connection.setDoOutput(true);
            OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
            out.write(inputString);
            out.close();

            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            Toast.makeText(MainActivity.this, in.toString(), Toast.LENGTH_LONG).show();

            in.close();
         catch (Exception e) 
            Log.e("YOUR_APP_LOG_TAG", "I got an error", e);
        
    
).start();

Logcat 结果:

app_url E/YOUR_APP_LOG_TAG:我收到一个错误 javax.net.ssl.SSLHandshakeException:握手失败 在 com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:429) 在 com.android.okhttp.Connection.connectTls(Connection.java:235) 在 com.android.okhttp.Connection.connectSocket(Connection.java:199) 在 com.android.okhttp.Connection.connect(Connection.java:172) 在 com.android.okhttp.Connection.connectAndSetOwner(Connection.java:367) 在 com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:130) 在 com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330) 在 com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:247) 在 com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:457) 在 com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:126) 在 com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:257) 在 com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218) 在 com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java) 在 com.example.cg_dte.app_url.MainActivity$1.run(MainActivity.java:41) 在 java.lang.Thread.run(Thread.java:760) 抑制:javax.net.ssl.SSLHandshakeException:握手失败 ... 15 更多 抑制:javax.net.ssl.SSLHandshakeException:握手失败 ... 15 更多 原因:javax.net.ssl.SSLProtocolException:SSL 握手 中止:ssl=0x7fa2258640:SSL 库失败,通常是协议 错误 错误:100000f7:SSL 例程:OPENSSL_internal:WRONG_VERSION_NUMBER (外部/boringssl/src/ssl/tls_record.c:192 0x7f94590e7e:0x00000000) 在 com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native 方法) 在 com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357) ... 14 更多 引起:javax.net.ssl.SSLProtocolException:SSL 握手中止: ssl=0x7fa2258640:SSL 库失败,通常是协议错误 错误:100000f7:SSL 例程:OPENSSL_internal:WRONG_VERSION_NUMBER (外部/boringssl/src/ssl/tls_record.c:192 0x7f94590e7e:0x00000000) 在 com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native 方法) 在 com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357) ... 14 更多 引起:javax.net.ssl.SSLProtocolException:SSL 握手中止: ssl=0x7fa2258640:SSL 库失败,通常是协议错误 错误:100000f7:SSL 例程:OPENSSL_internal:WRONG_VERSION_NUMBER (外部/boringssl/src/ssl/tls_record.c:192 0x7f94590e7e:0x00000000) 在 com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native 方法) 在 com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357) ... 14 更多

【问题讨论】:

尝试添加-Djavax.net.debug=all参数,获取SSL连接过程的详细信息。 【参考方案1】:

我遇到了同样的问题,我可以通过从 url 中删除 's' 来解决它。

请把网址改成

URL url = new URL("http://192.168.0.7:9999/WebS/welcome/test");

【讨论】:

你的“解决方案”然后是使用不安全的纯文本连接——这正在慢慢地在现代互联网上成为不受欢迎的角色。默认情况下,使用目标 SDK 26+(或 27+?)构建的应用程序将无法建立此类连接,您必须显式配置网络资源文件以强制设备接受与特定域的不安全连接。 这可能是我在 *** 上读到的最错误的答案【参考方案2】:
URL url = new URL("https://192.168.0.7:9999/WebS/welcome/test");

此 url 还包含端口规范(端口 9999)。确保您的 SSL 服务器实例(HTTPS 协议)配置为侦听该端口,可能是您错误地连接到服务器的非 SSL 实例(HTTP 协议)。

尝试例如不安全的URL url = new URL("http://192.168.0.7:9999/WebS/welcome/test"); 以查看该地址上的通信是否与 HTTP 协议一起工作。如果是,那么您需要连接到不同的 HTTPS 端口。最简单的办法是先尝试使用默认 SSL 端口 (443),即删除端口号:URL url = new URL("https://192.168.0.7/WebS/welcome/test");

您也可以在您最喜欢的浏览器中尝试所有这些 url 的变体,看看它对它的看法(我个人使用的是 firefox,端口指向 HTTP 的 url 确实会产生关于错误证书长度等的奇怪错误等。 .. 一旦我将我的 url 固定为指向 HTTPS 实例,firefox 确实报告了由于使用了自签名证书而导致的不安全连接,这是可以预料的和可以理解的。

如果您为本地服务器使用自签名证书,则正确的 HTTPS 网址可能会因javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 而失败,而无需进一步配置移动应用程序。这是不同的问题,有很多文档如何处理(以及如何固定证书、检查域名和创建安全连接)。

WRONG_VERSION_NUMBER (external/boringssl/src/ssl/tls_record.c: 建议您意外连接到服务器的未加密 HTTP 实例,然后 SSL 握手完全混乱。

【讨论】:

以上是关于javax.net.ssl.SSLProtocolException: SSL 握手中止: ssl=0x7fa2258640: SSL 库失败,通常是协议错误的主要内容,如果未能解决你的问题,请参考以下文章