带有 pem 证书的 RestTemplate
RestTemplate with pem certificate
我有带有私钥和服务器证书的 pem 证书。
我可以使用 curl 执行它,一切正常。
curl -O -k --cert-type pem --cert mypem.pem url
但我想将它与 java 一起使用,最好是来自 spring 的 RestTemplate。
您需要在 java 信任库中导入证书。
BTW pem 和 cer(t) 文件是相同的,只是扩展名不同
其他链接
- https://docs.oracle.com/cd/E19830-01/819-4712/ablqw/index.html
- Digital Certificate: How to import .cer file in to .truststore file using?
所以关于使用 RestTemplate 的 pem 证书的知识被分散了。
必须完成的步骤:
使用 keytool 或 portecle 将服务器证书添加到 trustStore。当您想使用自定义信任库时,请使用此 script
接下来配置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));
}
您终于可以使用注入 restTemplate 连接到 url。
我有带有私钥和服务器证书的 pem 证书。 我可以使用 curl 执行它,一切正常。
curl -O -k --cert-type pem --cert mypem.pem url
但我想将它与 java 一起使用,最好是来自 spring 的 RestTemplate。
您需要在 java 信任库中导入证书。
BTW pem 和 cer(t) 文件是相同的,只是扩展名不同
其他链接
- https://docs.oracle.com/cd/E19830-01/819-4712/ablqw/index.html
- Digital Certificate: How to import .cer file in to .truststore file using?
所以关于使用 RestTemplate 的 pem 证书的知识被分散了。
必须完成的步骤:
使用 keytool 或 portecle 将服务器证书添加到 trustStore。当您想使用自定义信任库时,请使用此 script
接下来配置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));
}
您终于可以使用注入 restTemplate 连接到 url。