簡體   English   中英

Java SSL - 使用 pkcs12 (.p12) 文件連接到安全 Rest 服務

[英]Java SSL - Connect to secure Rest Service using pkcs12 (.p12) file

我正在為我的 web 應用程序使用 rest 服務。 並且服務提供商提供了一個帶有密碼的.p12 文件來連接到他們的服務。

我在 postman 中安裝了證書文件以進行測試,它工作正常。現在我必須將它集成到我的 java 代碼中。

這是我的 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);
        }
    }
}

我總是得到如下回復。 這與我在沒有添加證書文件的情況下使用 postman 對其進行測試時得到的響應相同。

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

有人可以指出我在這里做錯了什么嗎?

我是 java 安全區域的新手。老實說,我按照指南編寫此代碼/嘗試連接時是否有要遵循的清單? (就像將文件添加到密鑰庫或信任庫一樣。至少有一個指南可以幫助我)

提前非常感謝。

你可以試試這個代碼嗎? 我對負載信任庫進行了一些更改。 確保從您的代碼中傳遞系統信任庫的路徑。

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:我無法驗證此代碼,因為我沒有證書和密鑰。 :)

您不必硬編碼任何東西來使其工作,只需為 Java 添加一些啟動參數,例如:

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

. (盡管它們隨后被應用程序中運行的所有線程和代碼共享,這可能是不可接受的)查看這個問題和提供的答案:

java SSL 和證書密鑰庫

此外,了解幕后發生的事情可能非常有用,您可以通過啟用一些額外的日志記錄來看到這些情況,例如:

-Djavax.net.debug=all

試試這個方法。我無法測試這個,因為我沒有證書文件,但我希望通過一些小的修改,它會起作用。

請將您的證書文件包含在資源文件夾中。

@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;
    }
}

讓我知道它是否有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM