Java中HTTP接口请求与HTTPS证书验证问题

Posted 飞鹰技术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中HTTP接口请求与HTTPS证书验证问题相关的知识,希望对你有一定的参考价值。

HTTP请求证书验证HTTPS通讯出错处理

HTTP是基于TCP/IP的应用层协议,简单、便捷。RESTFUL是一种基于HTTP的网络应用程序设计风格和开发方式,方便实现跨平台的业务接口。

HTTP请求

Java中通过HttpURLConnection可方便地进行HTTP请求:

String sendRequest(String strUrl, String strMethod, String strBody) {
    String strResult = "";
    try {
        URL url = new URL(strUrl);
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        httpConn.setRequestMethod(strMethod);
        httpConn.setDoInput(true);
        httpConn.setRequestProperty("Content-Type""application/json");

        if (strBody.length() > 0) { // Has body(for post-request)
            httpConn.setDoOutput(true);
            try (OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream(), StandardCharsets.UTF_8);
            ) {
                writer.write(strBody);
                writer.flush();
            }
        }

        // request now
        if (httpConn.getResponseCode() != HttpURLConnection.HTTP_OK) {
            throw new IOException(httpConn.getResponseMessage());
        }

        try (InputStreamReader inReader = new InputStreamReader(httpConn.getInputStream());
             BufferedReader buffReader = new BufferedReader(inReader);
        ) {
            String strLine;
            while ((strLine = buffReader.readLine()) != null) {
                strResult += strLine;
            }
        }
    } catch (IOException ex) {
        _logger.error("sendRequest({}) fail: {}", strUrl, ex);
    }

    return strResult;
}

请求的头(Headers)与URL一起通过第一个参数传入,请求的方式(POST、GET等)通过第二个参数传入,body通过第三个参数传入。

证书验证

在使用HTTPS请求时,若服务器的证书不是第三方信任机构颁发的(如自签名证书等),则会验证失败,然后报错(类似‘unable to find valid certification path to requested target’)。

HTTPS通讯

客户端在使用HTTPS与服务器通讯的基本流程:

  • 客户端通过HTTPS与服务器建立SSL连接;

  • 服务器在收到请求后,发送自身证书给客户端;

  • 客户端收到证书后,会对证书做验证(通过证书信任列表);浏览器等一般会弹出提示框,而Java请求中若发现证书不可信,则会报上面错误;

  • 客户端与服务器协商SSL连接安全等级;

  • 客户端根据协商等级建立会话密钥,并利用证书中公钥加密后发送给服务器;

  • 服务器使用对应私钥解密出会话密钥;

  • 两端使用会话密钥加密进行通讯。

出错处理

通过重写TrustManager的checkClientTrusted(检查客户端证书信任)和checkServerTrusted(检查服务端证书验证)。以及HostnameVerifier的verify(校验)方法即可取消对证书的所有验证。

static HostnameVerifier _hv = new HostnameVerifier() {
    @Override
    public boolean verify(String host, SSLSession sslSession) {
        _logger.warn("Host: {} VS {}", host, sslSession.getPeerHost());
        return true;
    }
};
static TrustManager[] _trustCerts = new TrustManager[]{
        new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        }
};

static {
    try {
        HttpsURLConnection.setDefaultHostnameVerifier(_hv);
        SSLContext ctxSSL = null;
        ctxSSL = SSLContext.getInstance("SSL");
        ctxSSL.init(null, _trustCerts, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(ctxSSL.getSocketFactory());
    } catch (Exception e) {
        _logger.error("SSL context set fail: {}", e);
    }
}

类中static代码会在类初次加载时调用一次;因验证代码影响是全局的,只要执行过,所有后续所有后续的请求都会生效。


以上是关于Java中HTTP接口请求与HTTPS证书验证问题的主要内容,如果未能解决你的问题,请参考以下文章

[接口测试_B] 10 requests处理SSL证书验证

Java的HttpClient如何去支持无证书访问https

c# https请求忽略证书验证_各种编程语言忽略http的SSL证书认证

向 wcf 服务发出 https 请求:根据验证程序,远程证书无效

httpclient绕过证书验证进行HTTPS请求

iOS笔记—NSURLConnection怎么把http改为https