java - 带有 pem 证书的 RestTemplate

标签 java spring authentication resttemplate pem

我有带有私钥和服务器证书的 pem 证书。 我可以使用 curl 执行它,一切正常。

curl -O -k --cert-type pem --cert mypem.pem url

但我想将它与 java 一起使用,最好是来自 spring 的 RestTemplate。

最佳答案

因此分散了有关将 pem 证书与 RestTemplate 一起使用的知识。

必须完成的步骤:

  1. 使用 keytool 或 portecle 将服务器证书添加到 trustStore。当您想使用自定义信任库时,请使用此 script

  2. 接下来将 ssl 配置到 RestTemplate。可以像下面这样完成:

    @Configuration
    public class SSLConfiguration {
    
    @Value("${certificate.name}")
    private String name;
    
    @Bean(name = "sslContext")
    public SSLContext sslContext() throws Exception {
      Security.addProvider(new BouncyCastleProvider());
      return SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).useTLS().build();
    }
    
    @Bean(name = "sslSocketFactory")
    public SSLSocketFactory sslSocketFactory() throws Exception {
    
      return new ConnectionFactoryCreator(name, sslContext()).getSocketFactory();
    
    }
    
    @Bean(name = "httpClient")
    public HttpClient httpClient() throws Exception {
      return HttpClientBuilder.create().setSslcontext(sslContext())
            .setSSLSocketFactory(new SSLConnectionSocketFactory(sslSocketFactory(), new AllowAllHostnameVerifier()))
            .build();
    }
    
    @Bean
    public ClientHttpRequestFactory httpClientRequestFactory() throws Exception {
      return new HttpComponentsClientHttpRequestFactory(httpClient());
    }
    
    @Bean
    public RestTemplate restTemplate() throws Exception {
      return new RestTemplate(httpClientRequestFactory());
     }
    
    }
    

public class ConnectionFactoryCreator {

   private final String pemName;

   private final SSLContext context;

   public ConnectionFactoryCreator(String pemName, SSLContext context) {
      this.pemName = pemName;
      this.context = context;
   }

   public SSLSocketFactory getSocketFactory() throws Exception {

      InputStream resourceAsStream = getClass().getResourceAsStream(pemName);
  byte[] certAndKey = ByteStreams.toByteArray(resourceAsStream);

  byte[] certBytes = parseDERFromPEM(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
  byte[] keyBytes = parseDERFromPEM(certAndKey, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----");

  X509Certificate cert = generateCertificateFromDER(certBytes);

  PrivateKey key = generatePrivateKeyFromDER(keyBytes);

  KeyStore keystore = KeyStore.getInstance("JKS");
  keystore.load(null);
  keystore.setCertificateEntry("cert-alias", cert);
  keystore.setKeyEntry("key-alias", key, "changeit".toCharArray(), new Certificate[] { cert });

  KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
  kmf.init(keystore, "changeit".toCharArray());

  KeyManager[] km = kmf.getKeyManagers();

  context.init(km, null, null);

  return context.getSocketFactory();
   }

   private byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter) {
  String data = new String(pem);
  String[] tokens = data.split(beginDelimiter);
  tokens = tokens[1].split(endDelimiter);
  return DatatypeConverter.parseBase64Binary(tokens[0]);
   }

   private PrivateKey generatePrivateKeyFromDER(byte[] keyBytes)
     throws InvalidKeySpecException, NoSuchAlgorithmException {
  PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);

  KeyFactory factory = KeyFactory.getInstance("RSA");

  return factory.generatePrivate(spec);
   }

   private X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException {
  CertificateFactory factory = CertificateFactory.getInstance("X.509");

  return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes));
 }

最后,您可以使用注入(inject) restTemplate 来连接到 url。

关于java - 带有 pem 证书的 RestTemplate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33497874/

相关文章:

java - 通过按钮使imageView可见和不可见

java - 在 Java 中检查新 XML 文件的最佳方法

java - 如何让 Jackson 的 LocalDateSerializer 呈现为 ISO 日期?

android-studio - 如何在 Android Studio Arctic Fox 中添加 GitHub 帐户

php - 验证当前 ssl 是否是服务器的 ssl

java - 如何在线程中创建一个TextView?

java - 解析依赖项时出现 Maven 错误

spring - 如何在spring中使用jdbcTemplate传递多个值进行查询

java - Spring 的 Redis 消息队列

database - postgresql super 用户没有密码提示