#java #spring #ssl #keystore
Вопрос:
Я пытаюсь вызвать службу https, размещенную в другом домене, для вызова которого требуется прокси-сервер, мне удалось загрузить сертификат в .pem
формате из браузера и добавить его в свою JVM с помощью keytool, но теперь я пытаюсь добавить его в свой keystore
при создании своего restTemplate
объекта, но когда я пытаюсь это сделать, я все еще получаю:
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed unable to find valid certification path to requested target
вот что я попробовал:
@Configuration
@Slf4j
public class RestTemplateFactory {
@Value("${certificate.name}")
private String name;
@Value("${PROXY_SERVER_HOST}")
private String proxyServerHost;
@Value("${PROXY_SERVER_PORT}")
private Integer proxyServerPort;
@Value("${NEED_PROXY}")
private boolean isNeedProxy;
@Value("${DOS_BASIC_AUTH_USERNAME}")
private String basicAuthDosUsername;
@Value("${DOS_BASIC_AUTH_PASSWORD}")
private String basicAuthDosPassword;
@Bean
public RestTemplate restTemplate() throws Exception {
return new RestTemplate(httpClientRequestFactory());
}
@Bean(name = "sslContext")
public SSLContext sslContext() throws Exception {
Security.addProvider(new BouncyCastleProvider());
return SSLContexts.custom()
.loadTrustMaterial(null, new TrustSelfSignedStrategy())
.useProtocol("TLS")
.build();
}
@Bean(name = "sslSocketFactory")
public SSLSocketFactory sslSocketFactory() throws Exception {
log.debug("Configure CERTIFICATE NAME:----> " name);
return new ConnectionFactoryCreator(name, sslContext()).getSocketFactory();
}
@Bean(name = "httpClient")
public CloseableHttpClient httpClient() throws Exception {
HttpHost proxy = new HttpHost(proxyServerHost, proxyServerPort);
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(basicAuthDosUsername, basicAuthDosPassword));
return HttpClientBuilder.create().setSslcontext(sslContext())
.setSSLSocketFactory(new SSLConnectionSocketFactory(sslSocketFactory(), new AllowAllHostnameVerifier()))
.setProxy(isNeedProxy ? proxy : null)
.setDefaultCredentialsProvider(credentialsProvider)
.build();
}
@Bean
public ClientHttpRequestFactory httpClientRequestFactory() throws Exception {
return new HttpComponentsClientHttpRequestFactory(httpClient());
}
}
И
@Slf4j
public class ConnectionFactoryCreator {
private String pemName;
private SSLContext context;
public ConnectionFactoryCreator(String pemName, SSLContext context) {
this.pemName = pemName;
this.context = context;
}
public SSLSocketFactory getSocketFactory() throws Exception {
log.debug("PEM CERTIFICATE NAME:----> " pemName);
InputStream resourceAsStream = getClass().getResourceAsStream("/keystore/" pemName);
byte[] certAndKey = IOUtils.toByteArray(resourceAsStream);
byte[] certBytes = parseDERFromPEM(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
X509Certificate cert = generateCertificateFromDER(certBytes);
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 X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException, CertificateException {
CertificateFactory factory = CertificateFactory.getInstance("X.509");
return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes));
}
}
Файл YAML:
certificate :
name : certificate.pem
и файл pem добавляется в /resources/keystore/certificate.pem
Комментарии:
1. пожалуйста, обратите внимание, что сертификат авторизован Amazon