Làm thế nào để sửa lỗi “java.security.cert.CertificateException: Không có tên thay thế chủ đề hiện diện”?


108

Tôi có một ứng dụng khách dịch vụ web Java, sử dụng dịch vụ web qua HTTPS.

import javax.xml.ws.Service;

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

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

Khi tôi kết nối với URL dịch vụ ( https://AAA.BBB.CCC.DDD:9443/ISomeService), tôi nhận được ngoại lệ java.security.cert.CertificateException: No subject alternative names present.

Để khắc phục, lần đầu tiên tôi chạy openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txtvà nhận được nội dung sau trong tệp certs.txt:

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, bây giờ tôi cần

  1. trích xuất phần certs.txtgiữa -----BEGIN CERTIFICATE----------END CERTIFICATE-----,
  2. sửa đổi nó để tên chứng chỉ bằng AAA.BBB.CCC.DDD
  3. sau đó nhập kết quả bằng cách sử dụng keytool -importcert -file fileWithModifiedCertificate(trong đó fileWithModifiedCertificatelà kết quả của hoạt động 1 và 2).

Điều này có chính xác?

Nếu vậy, chính xác thì làm cách nào để tôi có thể làm cho chứng chỉ từ bước 1 hoạt động với adddress ( AAA.BBB.CCC.DDD) dựa trên IP ?

Cập nhật 1 (23,10.2013 15:37 MSK): Trong câu trả lời cho một câu hỏi tương tự , tôi đọc như sau:

Nếu bạn không kiểm soát máy chủ đó, hãy sử dụng tên máy chủ của nó (miễn là có ít nhất CN khớp với tên máy chủ đó trong chứng chỉ hiện có).

Chính xác thì "sử dụng" có nghĩa là gì?

Câu trả lời:


153

Tôi đã khắc phục sự cố bằng cách tắt kiểm tra HTTPS bằng cách sử dụng phương pháp được trình bày ở đây :

Tôi đặt mã sau vào ISomeServicelớp:

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();
    }
}

Vì tôi chỉ sử dụng https://AAA.BBB.CCC.DDD:9443/ISomeServicecho mục đích thử nghiệm, nên đó là một giải pháp đủ tốt.


Cách tiếp cận được đề cập trong liên kết được đề cập ở trên dường như đã bị chặn ( nakov.com/blog/2009/07/16/… ). Bất cứ ai có thể cập nhật liên kết?
John

Tôi đã thử tắt xác thực trong quá trình này nhưng xác thực trình duyệt cho giao thức SSL (lỗ hổng Poodle) cho tôi: ssl_error_no_cypher_overlap. Bất kỳ ý tưởng?
will824

Xin chào, tôi nhận được org.springframework.web.client.HttpClientErrorException: 403 Forbidden

73
vô hiệu hóa kiểm tra HTTPS không phải là một "giải pháp". Bạn nên nói rằng tôi đã tìm thấy một "bản vá".
12

2
Điều này sẽ gây ra lỗ hổng trên Pre_prod và Production. Nhập máy chủ 1. Make trong hồ sơ cửa sổ lưu trữ 2. Hoặc nếu không add IP hoặc FQDN tên trên các lĩnh vực tên Chủ đề khác trong Certs
Shankar

34

Tôi cùng một vấn đề và đã giải quyết được bằng mã này. Tôi đặt mã này trước cuộc gọi đầu tiên đến dịch vụ web của mình.

javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
new javax.net.ssl.HostnameVerifier(){

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

Nó đơn giản và hoạt động tốt.

Đây là nguồn gốc.


3
Hoặc bạn có thể chỉ cần thay thế toàn bộ nội dung của hàm verify () bằng return hostname.equals("localhost");, nếu đó là điều bạn muốn làm. Là ifhoàn toàn thừa.
một CVn

Đây là một bản sửa lỗi đơn giản và nhanh chóng giúp chúng tôi thử nghiệm trong môi trường thử nghiệm của nhà cung cấp không có chứng chỉ thích hợp. Cảm ơn rất nhiều!
dacDave

@ JuanM.Hidalgo phù hợp với tôi, đã đặt mã ở trên ngay trước cuộc gọi tới HttpsURLConnection connection = (HttpsURLConnection) obj.openConnection();. Ngoài ra, điều này có bỏ qua mọi chứng chỉ không? Vì tôi thấy rằng cách giải quyết như vậy rất dễ bị bảo mật. Cảm ơn bạn!
ThunderWiring

câu trả lời này giải quyết ngoại lệ SSL cert của tôi và vấn đề phi vật LDH, tôi có thể thấy có một lỗi được báo cáo trong mở JDK, bugs.openjdk.java.net/browse/JDK-8170265
Akhil S Kamath

28

Đây là một câu hỏi cũ, nhưng tôi đã gặp vấn đề tương tự khi chuyển từ JDK 1.8.0_144 sang jdk 1.8.0_191

Chúng tôi đã tìm thấy một gợi ý trong bảng thay đổi:

Changelog

chúng tôi đã thêm thuộc tính hệ thống bổ sung sau, điều này đã giúp trong trường hợp của chúng tôi giải quyết vấn đề này:

-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true

25

Việc xác minh danh tính chứng chỉ được thực hiện dựa trên những gì khách hàng yêu cầu.

Khi máy khách của bạn sử dụng https://xxx.xxx.xxx.xxx/something( xxx.xxx.xxx.xxxđịa chỉ IP ở đâu), danh tính chứng chỉ được kiểm tra dựa trên địa chỉ IP này (về lý thuyết, chỉ sử dụng phần mở rộng IP SAN).

Nếu chứng chỉ của bạn không có IP SAN, nhưng có DNS SAN (hoặc nếu không có DNS SAN, Tên chung trong Chủ đề DN), bạn có thể làm cho điều này hoạt động bằng cách yêu cầu ứng dụng khách của bạn sử dụng URL có tên máy chủ đó thay thế (hoặc tên máy chủ mà chứng chỉ sẽ hợp lệ, nếu có nhiều giá trị có thể có). Ví dụ: nếu bạn cert có tên cho www.example.com, hãy sử dụng https://www.example.com/something.

Tất nhiên, bạn sẽ cần tên máy chủ đó để phân giải thành địa chỉ IP đó.

Ngoài ra, nếu có bất kỳ DNS SAN nào, CN trong Subject DN sẽ bị bỏ qua, vì vậy hãy sử dụng tên khớp với một trong các DNS SAN trong trường hợp này.


1
Tôi không thể truy cập dịch vụ qua http://www.example.com/someservice. Có đúng là để chứng chỉ hoạt động với địa chỉ dựa trên IP ( https://AAA.BBB.CCC.DDD:9443/ISomeService), tôi cần đặt tất cả các CNtrường thành AAA.BBB.CCC.DDD(thay thế someSubdomain.someorganisation.combằng AAA.BBB.CCC.DDDtrong tệp ở trên) và nhập tệp chứng chỉ kết quả không?
Mentiflectax

Bạn không thể làm bất cứ điều gì về CN hoặc cert nếu bạn không kiểm soát máy chủ.
Bruno

để truy cập vào các địa chỉ IP cho các mục đích thử nghiệm, bạn có thể thay đổi tạm thời của bạn /etc/hoststập tin hoặc tương đương
tyoc213

1
Trong mã của tôi, tôi đang gửi yêu cầu đến một IP công cộng, nhưng chứng chỉ CN là tên máy chủ. Vì vậy, trong mã của tôi, tôi đã thay thế IP bằng tên máy chủ và định cấu hình / etc / hosts của tôi để liên kết tên máy chủ này với IP. Đã giải quyết!
Leopold Gault

15

Để nhập chứng chỉ:

  1. Trích xuất chứng chỉ từ máy chủ, ví dụ: openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txtĐiều này sẽ trích xuất chứng chỉ ở định dạng PEM.
  2. Chuyển đổi cert thành định dạng DER vì đây là những gì keytool mong đợi, ví dụ: openssl x509 -in certs.txt -out certs.der -outform DER
  3. Bây giờ bạn muốn nhập chứng chỉ này vào tệp 'cacert' mặc định của hệ thống. Tìm tệp 'cacerts' mặc định của hệ thống để cài đặt Java của bạn. Hãy xem Làm thế nào để lấy vị trí của cacerts của cài đặt java mặc định?
  4. Nhập chứng chỉ vào tệp cacerts đó: sudo keytool -importcert -file certs.der -keystore <path-to-cacerts>Mật khẩu cacerts mặc định là 'changeit'.

Nếu chứng chỉ được cấp cho FQDN và bạn đang cố gắng kết nối bằng địa chỉ IP trong mã Java của mình, thì điều này có thể sẽ được sửa trong mã của bạn thay vì gây rối với chính chứng chỉ. Thay đổi mã của bạn để kết nối bằng FQDN. Nếu FQDN không thể phân giải được trên máy nhà phát triển của bạn, chỉ cần thêm nó vào tệp máy chủ của bạn hoặc định cấu hình máy của bạn với máy chủ DNS có thể giải quyết FQDN này.


"Nếu FQDN không thể giải quyết được trên máy phát triển của bạn, chỉ cần thêm nó vào tệp máy chủ của bạn" - đã giúp. Cảm ơn rất nhiều!
Woland

Tôi đã làm điều tương tự nhưng vẫn còn, vấn đề vẫn tiếp diễn. Có điều gì khác có thể được thực hiện bằng cách sử dụng cách tiếp cận này không?
pkgajulapalli

9

Tôi đã khắc phục sự cố này một cách đúng đắn bằng cách thêm tên thay thế của chủ đề vào chứng chỉ thay vì thực hiện bất kỳ thay đổi nào trong mã hoặc tắt SSL không giống như những gì các câu trả lời khác đề xuất ở đây. Nếu bạn thấy rõ ngoại lệ cho biết "Tên thay thế của chủ đề bị thiếu", do đó, cách thích hợp là thêm chúng

Vui lòng xem liên kết này để hiểu từng bước .

Lỗi trên có nghĩa là tệp JKS của bạn thiếu miền bắt buộc mà bạn đang cố truy cập ứng dụng. Bạn sẽ cần sử dụng Open SSL và công cụ chính để thêm nhiều miền

  1. Sao chép openssl.cnf vào thư mục hiện tại
  2. echo '[ subject_alt_name ]' >> openssl.cnf
  3. echo 'subjectAltName = DNS:example.mydomain1.com, DNS:example.mydomain2.com, DNS:example.mydomain3.com, DNS: localhost'>> openssl.cnf
  4. openssl req -x509 -nodes -newkey rsa:2048 -config openssl.cnf -extensions subject_alt_name -keyout private.key -out self-signed.pem -subj '/C=gb/ST=edinburgh/L=edinburgh/O=mygroup/OU=servicing/CN=www.example.com/emailAddress=postmaster@example.com' -days 365
  5. Xuất tệp khóa công khai (.pem) sang định dạng PKS12. Điều này sẽ nhắc bạn nhập mật khẩu

    openssl pkcs12 -export -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -export -in
    self-signed.pem -inkey private.key -name myalias -out keystore.p12
  6. Tạo a.JKS từ PEM tự ký (Kho khóa)

    keytool -importkeystore -destkeystore keystore.jks -deststoretype PKCS12 -srcstoretype PKCS12 -srckeystore keystore.p12
  7. Tạo Chứng chỉ từ tệp Keystore hoặc JKS ở trên

    keytool -export -keystore keystore.jks -alias myalias -file selfsigned.crt
  8. Vì chứng chỉ trên là Tự ký và không được xác thực bởi CA, nó cần được thêm vào Truststore (Tệp Cacerts ở vị trí bên dưới dành cho MAC, dành cho Windows, hãy tìm nơi cài đặt JDK của bạn).

    sudo keytool -importcert -file selfsigned.crt -alias myalias -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/cacerts

Câu trả lời gốc được đăng trên liên kết này ở đây .


4

Bạn có thể không muốn tắt tất cả Xác minh ssl và vì vậy bạn có thể chỉ cần tắt xác minh tên máy chủ thông qua điều này, điều này ít đáng sợ hơn một chút so với phương pháp thay thế:

HttpsURLConnection.setDefaultHostnameVerifier(
    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

[BIÊN TẬP]

Như đã đề cập bởi conapart3 SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIERhiện không được dùng nữa, vì vậy nó có thể bị xóa trong phiên bản mới hơn, vì vậy bạn có thể bị buộc phải tự triển khai trong tương lai, mặc dù tôi vẫn sẽ nói rằng tôi sẽ tránh xa bất kỳ giải pháp nào mà tất cả xác minh bị tắt.


2
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIERhiện không được dùng nữa.
conapart3

3

vấn đề của tôi khi gặp lỗi này đã được giải quyết bằng cách sử dụng URL đầy đủ "qatest.ourCompany.com/webService" thay vì chỉ "qatest / webService". Lý do là chứng chỉ bảo mật của chúng tôi có ký tự đại diện tức là "* .ourCompany.com". Sau khi tôi nhập địa chỉ đầy đủ, ngoại lệ đã biến mất. Hi vọng điêu nay co ich.


2

Đã trả lời nó rồi trong https://stackoverflow.com/a/53491151/1909708 .

Điều này không thành công vì cả tên chung của chứng chỉ ( CNtrong chứng nhận Subject) hoặc bất kỳ tên thay thế nào ( Subject Alternative Nametrong chứng chỉ) đều không khớp với tên máy chủ hoặc địa chỉ IP đích.

Ví dụ: từ JVM, khi cố gắng kết nối với địa chỉ IP ( WW.XX.YY.ZZ) chứ không phải tên DNS ( https://stackoverflow.com ), kết nối HTTPS sẽ không thành công vì chứng chỉ được lưu trữ trong kho tin cậy java yêu cầu cacertstên chung (hoặc tên thay thế của chứng chỉ như stackexchange.com hoặc * .stackoverflow.com, v.v.) để khớp với địa chỉ đích.

Vui lòng kiểm tra: https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#HostnameVerifier

    HttpsURLConnection urlConnection = (HttpsURLConnection) new URL("https://WW.XX.YY.ZZ/api/verify").openConnection();
    urlConnection.setSSLSocketFactory(socketFactory());
    urlConnection.setDoOutput(true);
    urlConnection.setRequestMethod("GET");
    urlConnection.setUseCaches(false);
    urlConnection.setHostnameVerifier(new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession sslSession) {
            return true;
        }
    });
    urlConnection.getOutputStream();

Ở trên, đã truyền một HostnameVerifierđối tượng được triển khai luôn trả về true:

new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession sslSession) {
            return true;
        }
    }

1

Đối với Spring Boot RestTemplate:

  • thêm org.apache.httpcomponents.httpcoresự phụ thuộc
  • sử dụng NoopHostnameVerifiercho nhà máy SSL:

    SSLContext sslContext = new SSLContextBuilder()
            .loadTrustMaterial(new URL("file:pathToServerKeyStore"), storePassword)
    //        .loadKeyMaterial(new URL("file:pathToClientKeyStore"), storePassword, storePassword)
            .build();
    SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
    CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(socketFactory).build();
    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(client);
    RestTemplate restTemplate = new RestTemplate(factory);

0

Tôi đã đến câu hỏi này sau khi nhận được thông báo lỗi tương tự. Tuy nhiên, trong trường hợp của tôi, chúng tôi có hai URL với các tên miền phụ khác nhau ( http://example1.xxx.com/someservicehttp://example2.yyy.com/someservice ) được dẫn đến cùng một máy chủ. Máy chủ này chỉ có một chứng chỉ ký tự đại diện cho miền * .xxx.com. Khi sử dụng dịch vụ thông qua tên miền thứ hai, chứng chỉ được tìm thấy (* .xxx.com) không khớp với tên miền được yêu cầu (* .yyy.com) và lỗi xảy ra.

Trong trường hợp này, chúng ta không nên cố gắng khắc phục lỗi như vậy bằng cách hạ thấp bảo mật SSL mà nên kiểm tra máy chủ và các chứng chỉ trên đó.


0
public class RESTfulClientSSL {

    static TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            // TODO Auto-generated method stub
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            // TODO Auto-generated method stub
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }
    }};

    public class NullHostNameVerifier implements HostnameVerifier {
        /*
         * (non-Javadoc)
         *
         * @see javax.net.ssl.HostnameVerifier#verify(java.lang.String,
         * javax.net.ssl.SSLSession)
         */
        @Override
        public boolean verify(String arg0, SSLSession arg1) {
            // TODO Auto-generated method stub
            return true;
        }
    }

    public static void main(String[] args) {

        HttpURLConnection connection = null;
        try {

            HttpsURLConnection.setDefaultHostnameVerifier(new RESTfulwalkthroughCer().new NullHostNameVerifier());
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());


            String uriString = "https://172.20.20.12:9443/rest/hr/exposed/service";
            URL url = new URL(uriString);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            //connection.setRequestMethod("POST");

            BASE64Encoder encoder = new BASE64Encoder();
            String username = "admin";
            String password = "admin";
            String encodedCredential = encoder.encode((username + ":" + password).getBytes());
            connection.setRequestProperty("Authorization", "Basic " + encodedCredential);

            connection.connect();
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                StringBuffer stringBuffer = new StringBuffer();
                String line = "";
                while ((line = reader.readLine()) != null) {
                    stringBuffer.append(line);
                }
                String content = stringBuffer.toString();
                System.out.println(content);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
}

1
vui lòng thêm văn bản giải thích vào mã của bạn. Xem stackoverflow.com/help/how-to-answer
jasie

1
Đây là một lỗ hổng bảo mật. Đây là cách người ta vô hiệu hóa xác minh chứng chỉ ngay từ đầu. Tất cả những ai sao chép giải pháp này sẽ tạo ra một lỗi bảo mật trong phần mềm của họ.
Marek Puchalski

0

Tôi đã xem qua SSL 2 chiều trong Springboot. Tôi đã thực hiện tất cả các cấu hình chính xác của dịch vụ máy chủ tomcat và trình gọi dịch vụ RestTemplate. nhưng tôi gặp lỗi là "java.security.cert.CertificateException: Không có tên thay thế chủ đề nào hiện diện"

Sau khi xem xét các giải pháp, tôi nhận thấy, JVM cần chứng chỉ này nếu không nó sẽ gây ra lỗi bắt tay.

Bây giờ, làm thế nào để thêm điều này vào JVM.

chuyển đến tệp jre / lib / security / cacerts. chúng ta cần thêm tệp chứng chỉ máy chủ của mình vào tệp cacerts này của jvm.

Lệnh thêm cert của máy chủ vào tệp cacerts thông qua dòng lệnh trong windows.

C: \ Program Files \ Java \ jdk1.8.0_191 \ jre \ lib \ security> keytool -import -noprompt -trustcacerts -alias sslserver -file E: \ spring_cloud_sachin \ ssl_keys \ sslserver.cer -keystore cacerts -storepass changeit

Kiểm tra chứng chỉ máy chủ đã được cài đặt hay chưa:

C: \ Program Files \ Java \ jdk1.8.0_191 \ jre \ lib \ security> keytool -list -keystore cacerts

bạn có thể xem danh sách các chứng chỉ đã cài đặt:

để biết thêm chi tiết: https://sachin4java.blogspot.com/2019/08/javasecuritycertcertificateexception-no.html


0

thêm mục nhập máy chủ có ip tương ứng với CN trong chứng chỉ

CN = someSubdomain.someorganisation.com

bây giờ cập nhật ip với tên CN nơi bạn đang cố gắng truy cập url.

Nó đã làm việc cho tôi.


0

Mã này sẽ hoạt động giống như charm và sử dụng đối tượng restTemple cho phần còn lại của mã.

  RestTemplate restTemplate = new RestTemplate();   
  TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
            @Override
            public boolean isTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) {
                return true;
            }

        };

        SSLContext sslContext = null;
        try {
            sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy)
                    .build();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(httpClient);

        restTemplate.setRequestFactory(requestFactory);
}

0

Khi bạn có chứng chỉ với cả CN và Tên thay thế chủ đề (SAN), nếu bạn đưa ra yêu cầu của mình dựa trên nội dung CN, thì nội dung cụ thể đó cũng phải có trong SAN, nếu không nó sẽ không thành công với lỗi được đề cập.

Trong trường hợp của tôi, CN đã có thứ gì đó, SAN có thứ khác. Tôi đã phải sử dụng URL SAN, và sau đó nó hoạt động tốt.


-3

Thêm địa chỉ IP của bạn vào tệp hosts. Địa chỉ này nằm trong thư mục C: \ Windows \ System32 \ drivers \ etc. Đồng thời thêm IP và Tên miền của địa chỉ IP. ví dụ: aaa.bbb.ccc.ddd abc@def.com


-5

Tôi đã giải quyết vấn đề bằng cách sau.

1. Tạo một lớp học. Lớp có một số triển khai trống

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. Tạo một phương pháp

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();
    }
}

  1. Gọi phương thức disableSSL () nơi ngoại lệ được ném ra. Nó hoạt động tốt.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.