RestTemplate with pem certificate

前端 未结 2 1391
星月不相逢
星月不相逢 2020-12-17 04:40

I have pem certificate with private key and server certificate. I can execute it using curl and all works ok.

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


        
2条回答
  •  醉梦人生
    2020-12-17 05:13

    So knowledge about using pem certificate with RestTemplate is distracted.

    Steps which must be done:

    1. Add server certificate to trustStore, using keytool or portecle. When you want to use custom trusttore use this script

    2. Next configure ssl to RestTemplate. It may be done like below:

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

    and

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

    Finally you can use inject restTemplate to connect to url.

提交回复
热议问题