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证书验证问题的主要内容,如果未能解决你的问题,请参考以下文章
Java的HttpClient如何去支持无证书访问https
c# https请求忽略证书验证_各种编程语言忽略http的SSL证书认证