在本地windows环境Java服务器 访问https服务器没有问题,换到测试环境linux服务器访问时出现上面这个问题,
是证书出问题了,服务器不信任我们自己创建的证书,所以在代码中必须要忽略证书信任问题。只要在创建connection之前调用两个方法:
trustAllHttpsCertificates();
HttpsURLConnection.setDefaultHostnameVerifier(hv);
两个方法的具体实现,如下:
- 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;
- //实例化SSL协议
- javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
- .getInstance("SSL");
- //实例化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;
- }
- }
以上的解决办法来自http://mengyang.iteye.com/blog/575671,在这里记录一下这个问题。
这里简单介绍下HostnameVerifier,这个接口主要是javax.net.ssl用于主机名验证的基接口。
其中verify()这个方法验证主机名和服务器验证方案,这里重写了这个方法在连接期间,如果URL的主机名和服务器名不匹配则验证机制可以回调此借口的实现程序来确定是否应该允许此链接。
TrustManager从Java API那看是
就是信任管理器负责管理在进行信任决策时使用的信任材料,以及决定是否应该接受对等方提供的凭据。通过使用TrustManagerFactory或通过实现TrustManager子类之一来创建信任管理器。
SSLContext类:
这个类的实例 代表socket协议实现,它作为socket工厂或SSLEngress的工厂。这个类用一组可选的密钥和信任管理器和安全随机字节的源进行初始化。Java平台的每一个实现都需要支持以下标准SSLVIEW协议。
HostnameVerifier接口:
在握手期间,如果URL的主机名和服务器的标识主机名不匹配,验证机制可以调用该接口的实现者来确定是否应该允许该连接。
这个策略可以是基于证书的,或者可以依赖于其他认证方案。当URL主机名验证的默认规则失败时,将使用这个回调。