【问题标题】:Handshake Failed using using okHttp but working using HttpURLConnection使用 okHttp 握手失败,但使用 HttpURLConnection 工作
【发布时间】:2018-01-30 21:11:03
【问题描述】:

我正在尝试向服务器发送 get 请求(发送 get 请求进行测试,实际上我需要向同一台服务器发送 post 请求。如果 get 有效,post 将有效)

到服务器的链接是 https://bits-bosm.org/2017/registrations/signup/

问题是当我使用 okHttp 发送请求时,我收到一个失败响应,说握手失败。

这是我使用 okHttp(在 kotlin 中)发送请求的代码

val request = Request.Builder()
            .url("https://bits-bosm.org/2017/registrations/signup/")
            .build()

    okHttpClient.newCall(request).enqueue(object : Callback {
        override fun onFailure(call: Call?, e: IOException?) {
            val mMessage = e?.message?.toString()
            Log.w("failure Response", mMessage)
        }

        override fun onResponse(call: Call?, response: Response?) {
            val mMessage = response?.body()?.string()
            Log.e("Message", mMessage)
        }
    })

但如果我使用 HttpUrlConnection 将 get 请求发送到同一台服务器,我会得到响应。

这是相同的代码(java)

private static final String USER_AGENT = "Mozilla/5.0";

private static final String GET_URL = "https://bits-bosm.org/2017/registrations/signup/";



static void sendGET() throws IOException {
    URL obj = new URL(GET_URL);
    HttpURLConnection con = (HttpURLConnection) obj.openConnection();
    con.setRequestMethod("GET");
    con.setRequestProperty("User-Agent", USER_AGENT);
    int responseCode = con.getResponseCode();
    System.out.println("GET Response Code :: " + responseCode);
    if (responseCode == HttpURLConnection.HTTP_OK) { // success
        BufferedReader in = new BufferedReader(new InputStreamReader(
                con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

        // print result
        Log.e("Result", response.toString());
    } else {
        System.out.println("GET request not worked");
    }

}

根据我在互联网上的搜索以及我可以推断的内容,问题是该站点是使用自我证书签名的,而 okHttp 不允许它们。我什至尝试使用我在 Internet 上找到的代码 sn-ps,它不检查证书(自定义 SSLSocketFactory)和其他一些解决方案,但它们都不起作用。我现在也不关心安全性,我只想让它工作。但我无法访问后端,也无法更改/删除 ssl 安全性。

怎样才能让它发挥作用?有什么我想念的吗?

【问题讨论】:

    标签: android ssl httpurlconnection okhttp


    【解决方案1】:

    这是广泛用作解决方法的不安全 OkHttpClient。

    不要在生产中使用它,它仅用于开发目的。

    import java.security.SecureRandom;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSession;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    import okhttp3.OkHttpClient;
    
    public class Http {
    
        private final static String SSL = "SSL";
    
        private static OkHttpClient InsecureHttpClient;
    
        public static OkHttpClient client () {
            if (InsecureHttpClient == null) {
                try {
                    InsecureHttpClient = insecureOkHttpClient ();
                } catch (Exception e) {
                    e.printStackTrace ();
                }
            }
    
            return InsecureHttpClient;
        }
    
        private static OkHttpClient insecureOkHttpClient () throws Exception {
            TrustManager [] trustAllCerts       = new TrustManager [] { trustManager () };
    
            SSLContext sslContext               = SSLContext.getInstance (SSL);
            sslContext.init (null, trustAllCerts, new SecureRandom ());
    
            SSLSocketFactory sslSocketFactory   = sslContext.getSocketFactory ();
    
            OkHttpClient.Builder builder        = new OkHttpClient.Builder ();
            builder.sslSocketFactory (sslSocketFactory, (X509TrustManager)trustAllCerts [0]);
            builder.hostnameVerifier (hostnameVerifier ());
    
            return builder.build ();
        }
    
        private static TrustManager trustManager () {
            return new X509TrustManager () {
    
                @Override
                public void checkClientTrusted (X509Certificate [] chain, String authType) throws CertificateException {  }
    
                @Override
                public void checkServerTrusted (X509Certificate[] chain, String authType) throws CertificateException {  }
    
                @Override
                public X509Certificate [] getAcceptedIssuers () {
                    return new X509Certificate [] {  };
                }
            };
        }
    
        private static HostnameVerifier hostnameVerifier () {
            return new HostnameVerifier () {
    
                @Override
                public boolean verify (String hostname, SSLSession session) {
                    return true;
                }
            };
        }
    }
    

    然后您显然可以使用上面的客户端,例如以下测试代码:(顺便说一句,它适用于您的 url)

    final Request request = new Request.Builder ()
        .url ("https://bits-bosm.org/2017/registrations/signup/")
        .get ()
        .addHeader ("Accept", "text/html")
        .build ();
    
    final OkHttpClient httpClient = Http.client ();
    
    new Thread (new Runnable () {
    
        @Override
        public void run () {
            try {
                Response response = httpClient.newCall (request).execute ();
    
                Logger.error (MainActivity.class.getSimpleName () + " --> Http Response", response.body ().string ());
    
            } catch (IOException e) {
                e.printStackTrace ();
            }
        }
    
    }).start ();
    

    【讨论】:

    • 正如我所说,我已经尝试过了,但它不起作用。它仍然将握手失败作为错误。我还提供了 URL,以备不时之需
    • 你显然没有测试过。我刚刚做了,它有效。在我编辑的答案中查看我的测试代码。
    • 感谢您的回复。好吧,我在评论之前确实尝试过,但它没有奏效。在寻找此问题的解决方案时,我发现 Android N 中有一些更改可能会阻止此问题。我正在使用 API 24,所以也许这不起作用。你在哪个 API 上试过这个?您还可以确认它适用于 API >= 24 吗?
    • @VaibhavMaheshwari,是的,它适用于 API >= 24。我已经在 API 25 上对其进行了测试,其余的应该都很好:)
    • 哦!我得到了它。 API 24 有一个错误阻止了这一点,我只在 API 24 上尝试了过去 12 小时。刚刚找到stackoverflow.com/questions/39133437/… 解释了这一点。我在 API 25 上进行了尝试,并且成功了。谢谢!顺便说一句,Android 端 API 24 有什么解决方法吗?
    猜你喜欢
    • 1970-01-01
    • 2021-11-14
    • 2014-10-07
    • 2023-03-14
    • 1970-01-01
    • 2018-10-03
    • 2018-05-16
    • 2010-09-16
    • 2018-07-28
    相关资源
    最近更新 更多