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

标签 java rest ssl keystore pkcs#12

我正在为我的网络应用程序使用休息服务。并且服务提供商提供了一个带有密码的 .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 安全领域的新手。老实说,我按照指南编写了这段代码/尝试连接时是否有要遵循的 list ? (比如将文件添加到 keystore 或信任库。至少有一个指南可以帮助我)

非常感谢。

最佳答案

试试这个方法。我无法测试这个,因为我没有证书文件,但我希望通过一些小的修改,它会起作用。

请将您的证书文件包含在资源文件夹中。

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

让我知道它是否有效。

关于Java SSL - 使用 pkcs12 (.p12) 文件连接到安全 Rest 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61153025/

相关文章:

iOS 提取证书身份 : EXC_BAD_ACCESS

java - 尝试访问文件作为资源时不支持的协议(protocol) : jndi with Websphere 6. 1

rest - 在 codeception 中将文件发送到 Restful 服务

unit-testing - soapUI 与 rest-assured 的 REST API 测试

iphone - iPhone 上的 SSL 问题

sql-server - 如何通过应用程序脚本通过 SSL 将 google 表格连接到 SQL Server

Java 2 ME GameCanvas -- 如何接收所有 keyPressed 事件?

java - Android 中的重新加载选项卡

java - 如何将循环中的阻塞调用更改为Java中的异步调用

spring - 未找到Spring Boot 2.2.5 404页面自定义json响应