我的springboot项目有问题。 我必须向其他服务器发送休息呼叫(https:/// ....)。 而且我还必须在java中使用cert key(.pem文件)。
当我在linux服务器(ubuntu)中使用curl命令时,我可以获得成功响应。
curl -X GET --cert <pem file path>:<password> https://<serverurl>:4443
但我的问题是我必须在Springboot java项目中使用RestTemplate。 所以我尝试配置几步,但我失败了。
有没有人知道在resttemplate中使用config cert(pem)?
我的RestTemplateConfig是
@Configuration
public class RestTemplateConfig {
private static Logger logger = LoggerFactory.getLogger(RestTemplateConfig.class);
@Autowired
private Environment env;
// .crt path
@Value("${cert.path}")
private String certFile;
// .p12 path
@Value("${bixby.reward.p12.path}")
private String p12File;
// .jks path
@Value("${http.client.ssl.trust-store}")
private Resource trustStore;
//password
@Value("${http.client.ssl.trust-store-password}")
private char[] trustStorePassword;
@Bean
public RestTemplate restTemplate() {
PoolingHttpClientConnectionManager cm = getConnectionManager(2000);
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(cm)
.setProxy(getProxyHost())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
HttpComponentsClientHttpRequestFactory componentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
componentsClientHttpRequestFactory.setHttpClient(httpClient);
componentsClientHttpRequestFactory.setConnectTimeout(Constants.CONNECTION_TIME_OUT);
componentsClientHttpRequestFactory.setReadTimeout(Constants.READ_TIME_OUT);
RestTemplate restTemplate = new RestTemplate(componentsClientHttpRequestFactory);
return restTemplate;
}
private HttpHost getProxyHost() {
HttpHost proxyHost = null;
String httpProxy = env.getProperty("http_proxy");
if(httpProxy != null) {
try {
String host = null;
int port = -1;
httpProxy = httpProxy.replace("https://", "").replace("http://", "");
String [] proxy = httpProxy.split(":");
host = proxy[0];
if(proxy.length == 1) {
port = 80;
} else {
port = Integer.parseInt(proxy[1]);
}
proxyHost = new HttpHost(host, port);
} catch(Exception e) {
logger.error("[IMPLICIT_ERROR] RestTemplate proxy setting error.", e);
}
}
return proxyHost;
}
private SSLConnectionSocketFactory getSSLSocketFactoryForNoVerification() {
SSLConnectionSocketFactory scsf = null;
try {
TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
File f= new File("");
SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial(null, acceptingTrustStrategy)
.build();
scsf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
} catch (Exception e) {
logger.error("[IMPLICIT_ERROR] RestTemplate ssl connection socket factory setting error.", e);
}
return scsf;
}
private SSLSocketFactory getSSLSocketFactory() {
SSLContext sslContext = null;
try {
InputStream certInputStream = new FileInputStream(certFile);
byte[] certAndKey = ByteStreams.toByteArray(certInputStream);
byte[] certBytes = parseDERFromCert(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
X509Certificate cert = generateCertificateFromDER(certBytes);
// private key
KeyStore pkeyStore = KeyStore.getInstance("PKCS12");
pkeyStore.load(new FileInputStream(p12File), trustStorePassword.toCharArray());
// "server" is alias
Key pvtKey = pkeyStore.getKey("server", trustStorePassword.toCharArray());
java.security.cert.Certificate[] keychain = pkeyStore.getCertificateChain("server");
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(null);
keystore.setCertificateEntry("cert-alias", cert);
keystore.setKeyEntry("key-alias", pvtKey, "changeit".toCharArray(), keychain);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keystore, "changeit".toCharArray());
TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
sslContext = SSLContexts.custom().loadTrustMaterial(keystore, acceptingTrustStrategy).build();
KeyManager[] km = kmf.getKeyManagers();
sslContext.init(km, null, null);
} catch (Exception e) {
logger.error("[IMPLICIT_ERROR] RestTemplate ssl connection socket factory setting error.", e);
}
return sslContext.getSocketFactory();
}
private PoolingHttpClientConnectionManager getConnectionManager(int maxTotal) {
SSLContext sslContext;
Registry<ConnectionSocketFactory> registry = null;
try {
sslContext = SSLContexts
.custom()
.loadTrustMaterial(trustStore.getFile(),
trustStorePassword)
.build();
// Since only our own certs are trusted, hostname verification is probably safe to bypass
HostnameVerifier hostnameVerifier = SSLConnectionSocketFactory.getDefaultHostnameVerifier();
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);//new NoopHostnameVerifier());
registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", new PlainConnectionSocketFactory())
//.register("https", getSSLSocketFactoryForNoVerification())
//.register("https", new SSLConnectionSocketFactory(getSSLSocketFactory(), new NoopHostnameVerifier()))
.register("https", sslSocketFactory)
.build();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
cm.setMaxTotal(maxTotal);
cm.setDefaultMaxPerRoute(maxTotal);
return cm;
}
private byte[] parseDERFromCert(byte[] cert, String beginDelimiter, String endDelimiter) {
String data = new String(cert);
String[] tokens = data.split(beginDelimiter);
tokens = tokens[1].split(endDelimiter);
return DatatypeConverter.parseBase64Binary(tokens[0]);
}
private X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException {
CertificateFactory factory = CertificateFactory.getInstance("X.509");
return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes));
}}