Java访问HTTPS时证书验证问题
为了尽可能避免安全问题,公司的很多系统服务都逐步https化,虽然开始过程会遇到各种问题,但趋势不改。最完美的https应用是能实现双向认证,客户端用私钥签名用服务端公钥加密,服务端用私钥签名客户端都公钥加密,但现实很多情况不可能让每个客户端都申请一个证书,因此只实现https的单项认证,即只要服务端又证书,客户端只验证https端证书可靠就可进行https通信。在某些情况下为了不花钱买第三方信任机构颁发都证书,客户端在一些情况下也不做服务器端都认证,两边只实现htts的加密通信。最近就遇到一个问题,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 {
- javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
- javax.net.ssl.TrustManager tm = new miTM();
- trustAllCerts[0] = tm;
- javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
- .getInstance("SSL");
- sc.init(null, trustAllCerts, null);
- javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
- .getSocketFactory());
- }
- static class miTM implements javax.net.ssl.TrustManager,
- javax.net.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);
http://blog.csdn.net/lizeyang/article/details/18983843
解决https证书验证不通过的问题
1、报错信息
java.security.cert.CertificateException: No name matching api.weibo.com found; nested exception is javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching api.weibo.com found原因:在调用api.weibo.com的时候,我们使用的是https的方式,正常情况下应该是使用api.weibo.com的证书,但由于某些原因,我们只能使用自己的证书,导致在验证证书的时候,就报了这个错误。
解决的办法:忽略服务端和客户端的证书校验即可。java 提供的相关的类。
2、具体实现方式
通过重写TrustManager的checkClientTrusted(检查客户端证书信任)和checkServerTrusted(检查服务端证书验证)。
以及HostnameVerifier的verify(校验)方法即可取消对证书的所有验证。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import javax.net.ssl.*;
import java.io.IOException;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate; public final class DisableSSLCertificateCheckUtil { private static final Logger LOGGER = LoggerFactory.getLogger(DisableSSLCertificateCheckUtil.class); /**
* Prevent instantiation of utility class.
*/ private DisableSSLCertificateCheckUtil() { } /**
* Disable trust checks for SSL connections.
*/ public static void disableChecks() {
try {
new URL("https://0.0.0.0/").getContent();
} catch (IOException e) {
// This invocation will always fail, but it will register the
// default SSL provider to the URL class.
}
try {
SSLContext sslc;
sslc = SSLContext.getInstance("TLS");
TrustManager[] trustManagerArray = {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[0];
}
}};
sslc.init(null, trustManagerArray, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
} catch (Exception e) {
LOGGER.error("error msg:{}", e);
throw new IllegalArgumentException("证书校验异常!");
}
}
}调用方式:
DisableSSLCertificateCheckUtil.disableChecks();影响的范围:将会影响整个tomcat里面对证书的验证。即通过tomcat里面的其他项目虽然没有执行这一段代码但是也同样会忽略证书的验证。
影响的时间:执行这段代码之后的所有时间都生效。
Java访问HTTPS时证书验证问题的更多相关文章
- java访问https绕过证书信任
package com.xing.test; import java.io.BufferedReader; import java.io.IOException; import java.io.Inp ...
- iOS UIWebView 访问https 绕过证书验证的方法
在文件开始实现 allowsAnyHTTPSCertificateForHost 方法 @implementation NSURLRequest (NSURLRequestWithIgnoreSSL ...
- iOS UIWebView 访问https绕过证书验证的方法
@implementation NSURLRequest (NSURLRequestWithIgnoreSSL) + (BOOL)allowsAnyHTTPSCertificateForHost:(N ...
- How to disable SSL certificate checking with Spring RestTemplate?(使用resttemplate访问https时禁用证书检查)
How to disable SSL certificate checking with Spring RestTemplate?(使用resttemplate访问https时禁用证书检查) **** ...
- java获取https网站证书,附带调用https:webservice接口
一.java 获取https网站证书: 1.创建一个java工程,新建InstallCert类,将以下代码复制进去 package com; import java.io.BufferedReader ...
- java实现https免证书认证
java实现https免证书认证 解决方法: 1.下载两个包,httpclient-4.2.jar和httpcore-4.2.jar,复制以下代码就可使用. 2.调用类代码: String htt ...
- 关于如何取消访问https时的提示:“此网站的安全证书存在问题”的解决方法
问题描述: 症状1:采用IE浏览器通过https/http协议访问网站时,总是提示:“此网站的安全证书存在问题.” 症状2:采用搜狗浏览器打开网页总是看到网页的图片等元素显示不完整,是一个X的小图片. ...
- java程序中访问https时,报 PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
在java中使用https访问数据时报异常: Caused by: sun.security.validator.ValidatorException: PKIX path building fail ...
- 微信支付HTTPS服务器证书验证指引
1. 背景介绍 2. 常见问题 3. 验证证书 4. 安装证书 背景介绍 微信支付使用HTTPS来保证通信安全, 在HTTPS服务器上部署了由权威机构签发的证书, 用于证明微信支付平台的真实身份. 商 ...
随机推荐
- P1146 硬币翻转
题目描述 在桌面上有一排硬币,共N枚,每一枚硬币均为正面朝上.现在要把所有的硬币翻转成反面朝上,规则是每次可翻转任意N-1枚硬币(正面向上的被翻转为反面向上,反之亦然).求一个最短的操作序列(将每次翻 ...
- 如何使用Visual Studio调试C#程序
当代码不能正常运行时,可以通过调试定位错误.常用的程序调试操作包括设置断点.开始.中断和停止程序的执行.单步执行程序以及使程序运行到指定的位置.下面将对这几种常用的程序调试操作进行详细地介绍. 1.断 ...
- (转)i686只是cpu的指令等级,包括32bit和64bit
i代表intel系列的cpu 386 几乎适用于所有的 x86 平台,不论是旧的 pentum 或者是新的 pentum-IV 与 K7 系列的 CPU等等,都可以正常的工作! 那个 i 指的是 In ...
- C# for 遍历 IPagedList
IPagedList<Doc> ss = Doclist.ToPagedList(page, pageSize); ;i<ss.Count;i++) { var yy = ss[i] ...
- icheck使用
1.使用: <link rel="stylesheet" href="css/skins/all.css">或者<link rel=" ...
- phpstorm 使用
常用快捷 ctrl + / 单行注释 Alt+1 隐藏左侧任务栏 设置 1:control+shift+A功能可以搜索对应功能,把mouse:Change font size(Zoom) ...的按钮 ...
- javeee 字节Buffered
package Zy; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io. ...
- 【转载】深入理解Java的接口和抽象类
深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...
- 【转载】JSP详解(四大作用域九大内置对象等)
前面讲解了Servlet,了解了Servlet的继承结构,生命周期等,并且在其中的ServletConfig和ServletContext对象有了一些比较详细的了解,但是我们会发现在Servlet中编 ...
- freemarker使用map替换字符串中的值
package demo01; import java.io.IOException;import java.io.OutputStreamWriter;import java.io.StringRe ...
