Java SSL - подключение к безопасной службе отдыха с использованием файла pkcs12 (.p12) - PullRequest
2 голосов
/ 11 апреля 2020

Я использую сервис отдыха для моего веб-приложения. И поставщик услуг предоставил файл .p12 с паролем для подключения к своей службе.

Я установил файл сертификата в почтальоне для целей тестирования, и он отлично работает. Теперь я должен интегрировать его в свой java code.

Это мой java код для интеграции.

import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.KeyManagerFactory;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;

@Service
public class DemoIntegration
{

    String key = "XYX";
    String value = "12BN";
    String encVal= "343fhh22343mm90ddfd61lcsert";
    private static String certPw = "44vvxxffx";  //Password to cerfificate file

    public void checkConnection()
    {
        try
        {
            RestTemplate restTemplate = new RestTemplate();
            HttpHeaders httpHeaders = new HttpHeaders();

            String uri = "https://my_demo_uri";

            KeyStore ks = KeyStore.getInstance("pkcs12");
            ks.load(new FileInputStream("C:\\Users\\my_cert.p12"), certPw.toCharArray()); //my_cert.p12 is my cerfificate file 

            KeyStore jks = KeyStore.getInstance("JKS");
            jks.load(null);

            for (Enumeration<String> t = ks.aliases(); t.hasMoreElements();)
            {
                String alias = t.nextElement();
                System.out.println("@:" + alias);
                if (ks.isKeyEntry(alias))
                {
                    Certificate[] a = ks.getCertificateChain(alias);
                    for (int i = 0; i < a.length; i++)
                    {
                        X509Certificate x509 = (X509Certificate) a[i];
                        System.out.println(x509.getSubjectDN().toString());
                        if (i > 0)
                        {
                            jks.setCertificateEntry(x509.getSubjectDN().toString(), x509);
                        }
                        System.out.println(ks.getCertificateAlias(x509));
                        System.out.println("ok");
                    }
                }
            }

            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, certPw.toCharArray());

            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
            tmf.init(jks);

            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
            httpHeaders.set("API_KEY", api_key);
            httpHeaders.set("Signature", SHA256Val);

            String r2 = restTemplate.exchange(uri, HttpMethod.GET, new HttpEntity<>(httpHeaders), String.class).getBody();
            System.out.println("Result " + r2);
        }
        catch (Exception ex)
        {
            System.out.println("Error " + ex.toString());
            Logger.getLogger(DemoIntegration.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

И всегда я получаю ответ, как показано ниже. Это тот же ответ, который я получил, когда тестировал его с почтальоном, не добавляя в него файл сертификата.

400 Bad Request:{
  "error": {
    "message": "No SSL cetificate"
  }
}

Может кто-нибудь указать, что я здесь не так делаю?

Я новичок ie, когда речь заходит о java зоне безопасности. Если честно, я следовал руководству по написанию этого кода / Есть ли контрольный список, которому нужно следовать при попытке подключения? (Как добавление файла в хранилище ключей или хранилище доверенных сертификатов. По крайней мере, руководство поможет мне здесь)

Заранее большое спасибо.

Ответы [ 3 ]

1 голос
/ 13 апреля 2020

Вам не нужно ничего жестко кодировать, чтобы заставить это работать, просто добавьте некоторые параметры запуска для Java, например:

-Djavax.net.ssl.keyStore=C:\Users\my_cert.p12

. (хотя они затем совместно используются всеми потоками и кодом, выполняемыми в вашем приложении, что может быть неприемлемо). Проверьте этот вопрос и предоставленные ответы:

java SSL и хранилище ключей сертификации

Кроме того, может быть очень полезно узнать, что происходит за занавесом, что можно увидеть, включив некоторые дополнительные журналы, например:

-Djavax.net.debug=all
1 голос
/ 15 апреля 2020

Попробуйте этот подход. Я не могу проверить это, так как у меня нет файла сертификата, но я надеюсь, что с некоторыми незначительными изменениями он будет работать.

Пожалуйста, включите ваш файл сертификата в папку ресурсов.

@Service
public class DemoIntegration
{
    String key = "XYX";
    String value = "12BN";
    String encVal= "343fhh22343mm90ddfd61lcsert";
    private static String certPw = "44vvxxffx";

    public void checkConnection()
    {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        httpHeaders.set("API_KEY", api_key);
        httpHeaders.set("Signature", SHA256Val);

        String uri = "https://my_demo_uri";

        try
        {
            RestTemplate restTemplate = getRestTemplateClientAuthentication();

            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
            httpHeaders.set("API_KEY", api_key);
            httpHeaders.set("Signature", SHA256Val);

            String r2 = restTemplate.exchange(uri, HttpMethod.GET, new HttpEntity<>(httpHeaders), String.class).getBody();
            System.out.println("Result " + r2);
        }
        catch (Exception ex)
        {
            System.out.println("Error " + ex.toString());
            Logger.getLogger(PesonetService.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private RestTemplate getRestTemplateClientAuthentication() throws Exception
    {
        TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;

        SSLContext sslContext = SSLContextBuilder
                .create()
                .loadKeyMaterial(ResourceUtils.getFile("classpath:my_cert.p12"),
                 certPw.toCharArray(), certPw.toCharArray())
                .build();

        CloseableHttpClient client = HttpClients.custom()
                .setSSLContext(sslContext)
                .build();

        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(client);

        RestTemplate restTemplate = new RestTemplate(requestFactory);
        return restTemplate;
    }
}

Дайте мне знать, если это работает.

1 голос
/ 13 апреля 2020

Можете попробовать этот код? Я внес некоторые изменения в загрузочную Truststore. Обязательно передайте путь к системе Truststore из вашего кода.

package com.jerry;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import javax.net.ssl.*;

import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.HttpClients;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;


public class SSLTest {
    private String api_key = "XYX";
    private  String api_secret = "12BN";
    private String SHA256Val = "343fhh633343mm90ddfd61lcsert";
    private static String certPw = "44vvxxffx";  //

    String trustStorePath = "C:/Program Files/Java/jre1.8.0_91/lib/security/cacerts";
    String trustStorePassword = "changeit"; // default trust store password

    public void checkConnection()
    {
        try
        {
//            RestTemplate restTemplate = new RestTemplate();
            HttpHeaders httpHeaders = new HttpHeaders();

            String uri = "https://my_demo_uri";

            KeyStore ks = KeyStore.getInstance("PKCS12");
            ks.load(new FileInputStream("C:\\Users\\IB\\Downloads\\my_cert.p12"), certPw.toCharArray()); //my_cert.p12 is my cerfificate file

            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(ks, certPw.toCharArray());
            KeyManager[] kms = kmf.getKeyManagers();

            KeyStore jks = KeyStore.getInstance("JKS");
            jks.load(new FileInputStream(trustStorePath), trustStorePassword.toCharArray());
//
//            for (Enumeration<String> t = ks.aliases(); t.hasMoreElements();)
//            {
//                String alias = t.nextElement();
//                System.out.println("@:" + alias);
//                if (ks.isKeyEntry(alias))
//                {
//                    Certificate[] a = ks.getCertificateChain(alias);
//                    for (int i = 0; i < a.length; i++)
//                    {
//                        X509Certificate x509 = (X509Certificate) a[i];
//                        System.out.println(x509.getSubjectDN().toString());
//                        if (i > 0)
//                        {
//                            jks.setCertificateEntry(x509.getSubjectDN().toString(), x509);
//                        }
//                        System.out.println(ks.getCertificateAlias(x509));
//                        System.out.println("ok");
//                    }
//                }
//            }


            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmf.init(jks);
            TrustManager[] tms = tmf.getTrustManagers();


            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
            SSLSocketFactory socketFactory = new SSLSocketFactory(ks, certPw, jks);

            HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(
                    socketFactory).build();
            ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(
                    httpClient);
            RestTemplate restTemplate = new RestTemplate(requestFactory);
            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
            httpHeaders.set("API_KEY", api_key);
            httpHeaders.set("Signature", SHA256Val);

            HttpEntity<String> entity = new HttpEntity<>("body", httpHeaders);

            String r2 = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class).getBody();
            System.out.println("Result " + r2);
        }
        catch (Exception ex)
        {
            System.out.println("Error " + ex.toString());
        }
    }
}

PS: я не смог проверить этот код, потому что у меня нет сертификата и ключа. :)

...