Java CertificateException“没有匹配IP地址的主题替代名称......找到”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29157861/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 07:28:11  来源:igfitidea点击:

Java CertificateException "No subject alternative names matching IP address ... found"

javasslipcertificate

提问by joz

I'm trying to implement a selfsigned certificate into my webserver, and it's working already with firefox and chrome (both from the server itself and from a remote machine)... but I can't get it to work with java. I've already created a keystore file that contains my certificate, but every time I try to connect to the Server it gives me a SSLHandshakeException: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names matching IP address 192.168.178.71 found

我正在尝试将自签名证书实施到我的网络服务器中,并且它已经在使用 firefox 和 chrome(来自服务器本身和远程机器)......但我无法让它与 java 一起工作。我已经创建了一个包含我的证书的密钥库文件,但是每次我尝试连接到服务器时,它都会给我一个 SSLHandshakeException:javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names matching IP address 192.168.178.71 found

The code I'm using for this test is:

我用于此测试的代码是:

public static void main(String[] args) {
         System.setProperty("javax.net.ssl.keyStore",                    HTTPStest.class.getResource("keystore.jks").getFile());
            System.setProperty("javax.net.ssl.keyStorePassword",           "lead"); 
        URL url;
            InputStream is = null;
            BufferedReader br;
            String line;

            try {
                url = new URL("https://192.168.178.71/");
                is = url.openStream();  // throws an IOException
                br = new BufferedReader(new InputStreamReader(is));

                while ((line = br.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (MalformedURLException mue) {
                 mue.printStackTrace();
            } catch (IOException ioe) {
                 ioe.printStackTrace();
            } finally {
                try {
                    if (is != null) is.close();
                } catch (IOException ioe) {
                    // nothing to see here
                }
            }

    }

And when checking my certificate with openssl it gives me this:

当用 openssl 检查我的证书时,它给了我这个:

 Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 2 (0x2)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=DE, ST=BY, L=MU, O=LEAD, CN=LEAD CA/[email protected]
        Validity
            Not Before: Mar 20 00:55:13 2015 GMT
            Not After : Mar 17 00:55:13 2025 GMT
        Subject: C=DE, ST=BY, L=BE, CN=192.168.178.71
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:ed:9b:27:2b:ab:7d:88:48:a3:21:54:98:24:be:
                    2d:72:4a:de:9c:05:de:95:3a:01:d5:46:09:d2:9c:
                    9f:29:b0:12:0c:86:28:88:51:a3:b9:c9:93:33:3c:
                    8a:5c:f2:fe:49:e2:1e:9e:5a:4b:fb:63:41:9a:13:
                    e5:bc:03:77:a0:5e:f2:b1:1f:db:f9:a4:03:07:8c:
                    41:54:8c:bc:2e:da:cd:72:67:5b:2f:d5:83:fd:d0:
                    bf:ea:bb:49:e0:21:2f:b3:f2:51:57:7c:81:d2:4b:
                    91:12:73:13:6a:29:3b:59:90:2d:8d:50:cc:2b:f2:
                    76:a8:41:ac:0a:11:8b:63:3b:d4:5c:91:5c:1e:41:
                    33:6f:3e:fe:ed:f4:c3:26:77:d9:e2:0b:2c:09:5c:
                    20:31:09:59:19:5c:15:75:eb:15:ef:b8:d8:7d:a2:
                    2d:f4:f8:7f:3a:7c:e0:ad:c0:3b:86:1e:4f:b1:b9:
                    c3:60:f8:fa:3c:5a:5a:72:bf:f9:95:c3:d4:8d:2b:
                    22:3f:f8:a2:37:b3:c2:16:fa:9e:2d:f9:b5:78:6d:
                    4f:88:95:84:12:f3:f5:c2:09:9f:51:ed:73:da:4d:
                    9b:c3:2f:99:6d:d7:e9:f3:e0:c4:8b:73:09:25:1f:
                    93:5c:dc:d7:fa:5c:47:59:ff:70:70:09:72:4a:8c:
                    3f:c5
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                FD:5F:79:74:31:E3:12:22:50:F8:C5:BE:A7:45:8B:10:65:8F:FC:A8
            X509v3 Authority Key Identifier: 
                keyid:C5:2F:3A:53:A7:AF:96:E2:25:09:46:8A:11:B6:B9:5D:79:55:04:D9

            X509v3 Basic Constraints: 
                CA:FALSE
            X509v3 Key Usage: 
                Digital Signature, Key Encipherment
            X509v3 Subject Alternative Name: 
                DNS:192.168.178.71, DNS:www.example.com, DNS:mail.example.com, DNS:ftp.example.com
            Netscape Comment: 
                OpenSSL Generated Certificate
    Signature Algorithm: sha256WithRSAEncryption
         7a:17:44:18:8e:31:11:b9:0a:fc:bf:d2:61:2f:16:24:56:24:
         11:04:9e:2e:dc:65:d1:31:12:af:3d:ff:57:80:6b:45:70:f2:
         e3:d8:2d:dd:d1:1d:05:ba:2e:92:d1:80:e8:93:0c:02:b2:47:
         d1:5c:10:54:cb:4d:e5:52:f4:1d:c4:d2:26:a5:8e:4c:a3:44:
         c0:6a:1d:74:27:89:6f:f4:dc:90:cc:3b:59:50:b7:38:5b:31:
         da:21:01:d4:e6:4f:7a:23:23:d5:c5:61:29:32:1a:1e:bb:f9:
         e1:3b:4f:a9:d8:d6:1d:f5:cf:15:04:18:8b:77:28:44:ef:ae:
         33:8c:1e:72:d6:8c:c4:cc:7c:17:b8:f4:e5:d0:34:4f:d5:3d:
         d7:59:4d:40:f3:42:1e:0c:26:98:73:98:a5:c2:d9:ea:2b:2a:
         05:c3:f5:0b:e1:b6:d7:91:4a:09:15:21:1b:bc:d1:96:5e:bd:
         47:9f:ab:27:e9:44:fc:00:e1:49:e4:74:1b:48:ff:56:01:03:
         e7:9b:d2:bc:0a:53:39:95:52:5f:de:d8:fe:10:e8:53:5f:b4:
         de:18:2d:50:a4:12:f8:48:37:66:4b:e1:18:21:69:ce:f3:0d:
         2f:3d:03:22:bf:f6:91:3f:23:0b:58:4f:5f:be:82:67:ab:65:
         98:15:e0:78:33:c6:50:38:39:42:ac:a5:bd:13:16:ca:58:64:
         ce:a7:e8:88:e8:2f:eb:d5:7e:9e:75:51:da:50:b4:41:d1:83:
         a8:a8:a3:18:25:b8:87:9d:c8:18:a0:db:7a:57:b1:31:e3:34:
         a8:92:b7:4b:75:c4:34:09:3d:a2:de:69:b2:d5:2f:9e:97:b7:
         c8:b5:df:8a:a8:d8:e2:b0:96:9e:56:39:40:c5:64:bf:fb:b2:
         b8:cb:e1:29:24:a7:ce:00:34:d6:a9:11:c4:bf:8e:ae:c8:5c:
         50:38:42:b9:15:9e:db:6b:00:ff:93:e8:0a:d3:00:13:0a:31:
         3b:cc:93:ad:92:09:9d:97:dd:42:28:07:43:91:39:86:2e:54:
         97:4a:a6:57:96:07:69:90:62:58:eb:0b:39:44:05:74:ad:f5:
         bc:6a:41:5e:79:dd:27:99:32:67:c3:82:14:df:4b:44:a9:7e:
         63:29:4e:c3:a3:ef:fa:1d:14:da:54:77:fb:6c:d8:c6:cc:5f:
         99:06:38:f0:2c:78:41:f7:a1:5a:d6:29:1d:5f:df:f9:3b:7b:
         cf:9f:73:f3:6c:b4:cf:0b:8e:39:7a:f1:35:3e:8d:66:12:4f:
         f4:b1:04:6c:1f:d6:27:75:91:43:82:a4:74:a8:77:84:f9:ca:
         14:71:8a:ac:da:3b:39:2d

Can anyone help me solve this problem? I know that I could just go for a hostname, but I would like to have it work this way too

谁能帮我解决这个问题?我知道我可以只使用主机名,但我也希望它以这种方式工作

采纳答案by Liu guanghua

Your certificate should include that ip value as a subject alternative name value (of type IPAddress : key=7).

您的证书应包含该 ip 值作为主题备用名称值(IPAddress 类型:key=7)。

http://www.jroller.com/hasant/entry/no_subject_alternative_names_matching

http://www.jroller.com/hasant/entry/no_subject_alternative_names_matching

回答by Aditya Bhuyan

I have solved the issue using 3 Steps

我已经使用 3 个步骤解决了这个问题

  1. Creating a class . The class has some empty implementations

    class MyTrustManager implements X509TrustManager 
    {
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
       return null;
    }
    
    public void checkClientTrusted(X509Certificate[] certs, String authType) {
    }
    
    public void checkServerTrusted(X509Certificate[] certs, String authType) {
    }
    
    @Override
     public void checkClientTrusted(java.security.cert.X509Certificate[]      paramArrayOfX509Certificate, String paramString)
        throws CertificateException {
      // TODO Auto-generated method stub
    
    }
    
    @Override
    public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString)
            throws CertificateException {
        // TODO Auto-generated method stub
    
    }
    
  2. Creating a method

    private static void disableSSL() {
          try {
             TrustManager[] trustAllCerts = new TrustManager[] { new   MyTrustManager() };
    
        // Install the all-trusting trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (Exception e) {
        e.printStackTrace();
    }}
    
  3. Call the disableSSL() method from where exception being thrown. It worked fine.

  1. 创建一个类。该类有一些空的实现

    class MyTrustManager implements X509TrustManager 
    {
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
       return null;
    }
    
    public void checkClientTrusted(X509Certificate[] certs, String authType) {
    }
    
    public void checkServerTrusted(X509Certificate[] certs, String authType) {
    }
    
    @Override
     public void checkClientTrusted(java.security.cert.X509Certificate[]      paramArrayOfX509Certificate, String paramString)
        throws CertificateException {
      // TODO Auto-generated method stub
    
    }
    
    @Override
    public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString)
            throws CertificateException {
        // TODO Auto-generated method stub
    
    }
    
  2. 创建方法

    private static void disableSSL() {
          try {
             TrustManager[] trustAllCerts = new TrustManager[] { new   MyTrustManager() };
    
        // Install the all-trusting trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (Exception e) {
        e.printStackTrace();
    }}
    
  3. 从抛出异常的地方调用 disableSSL() 方法。它工作得很好。

回答by Abhishek Galoda

The reason, we get above error is that CN(Common name) defined in your certificate is not matching with the domain the application is running on. For e.g, In your certificate, the CN name is defined as www.example.com or an IP but you may be running the application say a URL which is like http://localhost:8080/api

我们得到上述错误的原因是您的证书中定义的 CN(Common name) 与运行应用程序的域不匹配。例如,在您的证书中,CN 名称被定义为 www.example.com 或 IP,但您可能正在运行应用程序,说一个类似于http://localhost:8080/api的 URL

So to fix the above error simply use one of the below approaches

因此,要修复上述错误,只需使用以下方法之一

Run the application on the same ‘CN', as defined in your certificates.

在证书中定义的同一个“CN”上运行应用程序。

OR

或者

Along with CN name you can add Subject alt names in your certificate, which is like adding more than one domain in the certificate. Link below describes the process of adding multiple domains(subject-alt-name) to jks file and also to a certificate.

除了 CN 名称,您还可以在证书中添加主题替代名称,这就像在证书中添加多个域一样。下面的链接描述了将多个域(subject-alt-name)添加到 jks 文件和证书的过程。

Follow this link: Learn how to add subject alt names and resolve the above error

按照此链接:了解如何添加主题替代名称并解决上述错误

回答by Himadri Pant

The reason why this fails is because the hostname of the target endpoint and the certificate common name (CNin certification Subjectdoes not match).

失败的原因是目标端点的主机名和证书公用名(CN在认证Subject中不匹配)。

For e.g., from a JVM, when trying to connect to an IP address (WW.XX.YY.ZZ) and not the DNS name (https://stackoverflow.com), the HTTPS connection will fail because the certificate stored in the java truststore cacertsexpects common name to match the target address.

例如,在 JVM 中,当尝试连接到 IP 地址 ( WW.XX.YY.ZZ) 而不是 DNS 名称 ( https://stackoverflow.com) 时,HTTPS 连接将失败,因为存储在 java 信任库中的证书cacerts需要通用名称匹配目标地址。

To mitigate this HostnameVerifier needs to be verify the connection despite the mismatch https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#HostnameVerifier

为了缓解这个 HostnameVerifier 需要验证连接,尽管不匹配 https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#HostnameVerifier

    HttpsURLConnection urlConnection = (HttpsURLConnection) new URL("https://test.test/api").openConnection();
    urlConnection.setSSLSocketFactory(buildSocketFactory());
    urlConnection.setDoOutput(true);
    urlConnection.setRequestMethod("get");
    urlConnection.setHostnameVerifier(new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession sslSession) {
            return true;
        }
    });
    urlConnection.getOutputStream();

回答by Jonathan Mendoza

Execute the following steps

执行以下步骤

1- Modify the file: /etc/ssl/openssl.cnf, for example:

1- 修改文件:/etc/ssl/openssl.cnf,例如:

subjectAltName=DNS:api.electoralsystem

2- Generate private key

2- 生成私钥

jmendoza@jmendoza:~$ openssl genrsa -aes256 -out electoralsystem-cakey.pem 2048 -alias electoralsystem-cakey.pem
Generating RSA private key, 2048 bit long modulus
....................+++++
.......................................+++++
e is 65537 (0x010001)
Enter pass phrase for electoralsystem-cakey.pem:
Verifying - Enter pass phrase for electoralsystem-cakey.pem:

3- Generate cacert x509

3- 生成 cacert x509

jmendoza@jmendoza:~$ openssl req -new -x509 -sha256 -key electoralsystem-cakey.pem -days 365 -out electoralsystem-cacert.pem 
Enter pass phrase for electoralsystem-cakey.pem:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:VE
State or Province Name (full name) [Some-State]:CARACAS
Locality Name (eg, city) []:CARACAS
Organization Name (eg, company) [Internet Widgits Pty Ltd]:JMENDOZA
Organizational Unit Name (eg, section) []:TI
Common Name (e.g. server FQDN or YOUR name) []:api.electoralsystem
Email Address []:[email protected] 

openssl x509 -in electoralsystem-cacert.pem -text

openssl x509 -in 选举系统-cacert.pem -text

4- Generate keystore pkcs12

4- 生成密钥库 pkcs12

jmendoza@jmendoza:~$ openssl pkcs12 -export -in electoralsystem-cacert.pem -inkey electoralsystem-cakey.pem -out electoralsystem-store.p12 -name "electoralsystem-store" 
Enter pass phrase for electoralsystem-cakey.pem:
Enter Export Password:
Verifying - Enter Export Password:

5- If you need it, convert the PKCS12 keystore to JKS keytstore using keytool command

5- 如果需要,请使用 keytool 命令将 PKCS12 密钥库转换为 JKS 密钥库

jmendoza@jmendoza:~$ keytool -importkeystore -destkeystore electoralsystem-store.jks -deststorepass jmendoza -srckeystore electoralsystem-store.p12 -srcstoretype PKCS12 -srcstorepass jmendoza -alias electoralsystem-store
Importando el almacén de claves de electoralsystem-store.p12 a electoralsystem-store.jks...

6- On the client, import certificate in keytstore

6- 在客户端,在 keytstore 中导入证书

jmendoza@jmendoza:~$ keytool -importcert -file electoralsystem-cacert.pem -keystore ldap-server-smmt.jks 
Introduzca la contrase?a del almacén de claves:

Import certificate in keytstore

在密钥库中导入证书

Invoke API - https://api.electoralsystem:8081/yyyy/xxxxx

调用 API - https://api.electoralsystem:8081/yyyy/xxxxx

7- Configure certificates on the api server

7- 在 api 服务器上配置证书

Configure certificates on the api server

在 api 服务器上配置证书

8- Summary generated files

8- 汇总生成的文件

jmendoza@jmendoza:~$ ls -lt
total 1332
-rw-rw-r--  1 jmendoza jmendoza    2482 jul 25 10:15  ldap-server-smmt.jks
-rw-r--r--  1 jmendoza jmendoza    2442 jul 25 10:04  electoralsystem-store.jks
-rw-------  1 jmendoza jmendoza    2792 jul 25 10:01  electoralsystem-store.p12
-rw-r--r--  1 jmendoza jmendoza    1509 jul 25 09:45  electoralsystem-cacert.pem
-rw-------  1 jmendoza jmendoza    1766 jul 25 09:38  electoralsystem-cakey.pem

Note: configure DNS api.electoralsystem on the client's docker or server

注意:在客户端的docker或者服务器上配置DNS api.electoralsystem