700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > jodd忽略ssl证书_关于java访问https资源时 忽略证书信任问题

jodd忽略ssl证书_关于java访问https资源时 忽略证书信任问题

时间:2021-07-19 21:50:31

相关推荐

jodd忽略ssl证书_关于java访问https资源时 忽略证书信任问题

java程序在访问https资源时,出现报错

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

这本质上,是java在访问https资源时的证书信任问题。

如何解决这个问题呢?

解决这个问题前,要了解

1)https通信过程

客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤,如图所示。

(1)客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。

(2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。

(3)客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。

(4)客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。

(5)Web服务器利用自己的私钥解密出会话密钥。

(6)Web服务器利用会话密钥加密与客户端之间的通信。

2)java程序的证书信任规则

如上文所述,客户端会从服务端拿到证书信息。调用端(客户端)会有一个证书信任列表,拿到证书信息后,会判断该证书是否可信任。

如果是用浏览器访问https资源,发现证书不可信任,一般会弹框告诉用户,对方的证书不可信任,是否继续之类。

Java虚拟机并不直接使用操作系统的keyring,而是有自己的security manager。与操作系统类似,jdk的security manager默认有一堆的根证书信任。如果你的https站点证书是花钱申请的,被这些根证书所信任,那使用java来访问此https站点会非常方便。因此,如果用java访问https资源,发现证书不可信任,则会报文章开头说到的错误。

解决问题的方法

1)将证书导入到jdk的信任证书中(理论上应该可行,未验证)

2)在客户端(调用端)添加逻辑,忽略证书信任问题

第一种方法,需要在每台运行该java程序的机器上,都做导入操作,不方便部署,因此,采用第二种方法。下面贴下该方法对应的代码。

验证可行的代码

1)先实现验证方法

HostnameVerifier hv = new HostnameVerifier() {

public boolean verify(String urlHostName, SSLSession session) {

System.out.println("Warning: URL Host: " + urlHostName + " vs. "

+ session.getPeerHost());

return true;

}

};

private static void trustAllHttpsCertificates() throws Exception {

.ssl.TrustManager[] trustAllCerts = new .ssl.TrustManager[1];

.ssl.TrustManager tm = new miTM();

trustAllCerts[0] = tm;

.ssl.SSLContext sc = .ssl.SSLContext

.getInstance("SSL");

sc.init(null, trustAllCerts, null);

.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc

.getSocketFactory());

}

static class miTM implements .ssl.TrustManager,

.ssl.X509TrustManager {

public java.security.cert.X509Certificate[] getAcceptedIssuers() {

return null;

}

public boolean isServerTrusted(

java.security.cert.X509Certificate[] certs) {

return true;

}

public boolean isClientTrusted(

java.security.cert.X509Certificate[] certs) {

return true;

}

public void checkServerTrusted(

java.security.cert.X509Certificate[] certs, String authType)

throws java.security.cert.CertificateException {

return;

}

public void checkClientTrusted(

java.security.cert.X509Certificate[] certs, String authType)

throws java.security.cert.CertificateException {

return;

}

}

2)在访问https资源前,调用

trustAllHttpsCertificates();

HttpsURLConnection.setDefaultHostnameVerifier(hv);

以下是一个具体的例子:

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import .HttpURLConnection;

import .URL;

import .ssl.HostnameVerifier;

import .ssl.HttpsURLConnection;

import .ssl.SSLSession;

import org.apache.log4j.Logger;

import org.htmlparser.util.ParserException;

import com.xwtech.parser.GetRequestHtmlParser;

import com.xwtech.pojo.ExtendCandidate;

/*

* GET请求类

*/

public class GetRequest {

private String url = "/b2b/main/viewNoticeContent.html?noticeBean.id=";

private Logger logger;

public GetRequest() {

logger = Logger.getLogger(GetRequest.class);

}

private static void trustAllHttpsCertificates() throws Exception {

.ssl.TrustManager[] trustAllCerts = new .ssl.TrustManager[1];

.ssl.TrustManager tm = new miTM();

trustAllCerts[0] = tm;

.ssl.SSLContext sc = .ssl.SSLContext.getInstance("SSL");

sc.init(null, trustAllCerts, null);

.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

}

public void getData(String id) {

this.url = url + id;

BufferedReader in = null;

HttpURLConnection conn = null;

String result = "";

try {

//该部分必须在获取connection前调用

trustAllHttpsCertificates();

HostnameVerifier hv = new HostnameVerifier() {

public boolean verify(String urlHostName, SSLSession session) {

logger.info("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());

return true;

}

};

HttpsURLConnection.setDefaultHostnameVerifier(hv);

conn = (HttpURLConnection)new URL(url).openConnection();

// 发送GET请求必须设置如下两行

conn.setDoInput(true);

conn.setRequestMethod("GET");

// flush输出流的缓冲

in = new BufferedReader(new InputStreamReader(conn.getInputStream()));

String line;

while ((line = in.readLine()) != null) {

result += line;

}

} catch (Exception e) {

logger.error("发送 GET 请求出现异常!\t请求ID:"+id+"\n"+e.getMessage()+"\n");

} finally {// 使用finally块来关闭输出流、输入流

try {

if (in != null) {

in.close();

}

} catch (IOException ex) {

logger.error("关闭数据流出错了!\n"+ex.getMessage()+"\n");

}

}

// 获得相应结果result,可以直接处理......

}

static class miTM implements .ssl.TrustManager, .ssl.X509TrustManager {

public java.security.cert.X509Certificate[] getAcceptedIssuers() {

return null;

}

public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) {

return true;

}

public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) {

return true;

}

public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)

throws java.security.cert.CertificateException {

return;

}

public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)

throws java.security.cert.CertificateException {

return;

}

}

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。