首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何修复"java.security.cert.CertificateException: No subject alternative names present“错误?

如何修复"java.security.cert.CertificateException: No subject alternative names present“错误?
EN

Stack Overflow用户
提问于 2013-10-23 19:23:27
回答 23查看 504.7K关注 0票数 135

我有一个Java web服务客户端,它通过HTTPS使用web服务。

代码语言:javascript
复制
import javax.xml.ws.Service;

@WebServiceClient(name = "ISomeService", targetNamespace = "http://tempuri.org/", wsdlLocation = "...")
public class ISomeService
    extends Service
{

    public ISomeService() {
        super(__getWsdlLocation(), ISOMESERVICE_QNAME);
    }

当我连接到服务URL (https://AAA.BBB.CCC.DDD:9443/ISomeService )时,我得到异常java.security.cert.CertificateException: No subject alternative names present

为了解决这个问题,我首先运行了openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt,并在文件certs.txt中获得了以下内容

代码语言:javascript
复制
CONNECTED(00000003)
---
Certificate chain
 0 s:/CN=someSubdomain.someorganisation.com
   i:/CN=someSubdomain.someorganisation.com
-----BEGIN CERTIFICATE-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=someSubdomain.someorganisation.com
issuer=/CN=someSubdomain.someorganisation.com
---
No client certificate CA names sent
---
SSL handshake has read 489 bytes and written 236 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-MD5
Server public key is 512 bit
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : RC4-MD5            
    Session-ID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    Session-ID-ctx:                 
    Master-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    Key-Arg   : None
    Start Time: 1382521838
    Timeout   : 300 (sec)
    Verify return code: 21 (unable to verify the first certificate)
---

AFAIK,现在我需要

  1. 提取-----BEGIN CERTIFICATE----------END CERTIFICATE-----之间的certs.txt部分,
  2. 对其进行修改,使证书名称等于AAA.BBB.CCC.DDD
  3. ,然后使用keytool -importcert -file fileWithModifiedCertificate导入结果(其中D17是操作1和2的结果)。

这是正确的吗?

如果是这样,我如何使步骤1中的证书与基于IP的地址(AAA.BBB.CCC.DDD)一起工作?

更新1 (23.10.2013 15:37MSK):在回答similar question时,我读到了以下内容:

如果您无法控制该服务器,请使用它的主机名(前提是现有证书中至少有一个CN与该主机名匹配)。

"use“到底是什么意思?

EN

回答 23

Stack Overflow用户

回答已采纳

发布于 2013-10-23 21:09:34

我通过使用here提供的方法禁用了HTTPS检查,修复了这个问题

我将以下代码放入ISomeService类中:

代码语言:javascript
复制
static {
    disableSslVerification();
}

private static void disableSslVerification() {
    try
    {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        }
        };

        // Install the all-trusting trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        // Create all-trusting host name verifier
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        // Install the all-trusting host verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }
}

由于我仅将https://AAA.BBB.CCC.DDD:9443/ISomeService用于测试目的,因此它是一个足够好的解决方案,但不要在生产中这样做。

请注意,您还可以为“一次一个连接”禁用SSL,例如:

代码语言:javascript
复制
 // don't call disableSslVerification but use its internal code:
 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 if (conn instanceof HttpsURLConnection) {
    HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
    httpsConn.setHostnameVerifier(allHostsValid);
    httpsConn.setSSLSocketFactory(sc.getSocketFactory());
 }
票数 172
EN

Stack Overflow用户

发布于 2015-06-24 12:05:47

我也有同样的问题,并用这段代码解决了。我把这段代码放在第一次调用我的put服务之前。

代码语言:javascript
复制
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
  new javax.net.ssl.HostnameVerifier(){

      public boolean verify(String hostname,
             javax.net.ssl.SSLSession sslSession) {
          return hostname.equals("localhost"); // or return true
      }
  });

它很简单,运行得很好。

Here是原始源。

票数 39
EN

Stack Overflow用户

发布于 2018-11-01 21:40:17

这是一个老问题,但我在从JDK 1.8.0_144迁移到jdk 1.8.0_191时也遇到了同样的问题。

我们在changelog中发现了一个提示:

Changelog

我们添加了以下附加系统属性,这在我们的案例中帮助解决了这个问题:

代码语言:javascript
复制
-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true
票数 36
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19540289

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档