Java 我可以';nt使用pem在resttemplate中设置证书
我的springboot项目有问题。 我必须向其他服务器发送rest调用(https:///....). 我还必须在java中使用证书密钥(.pem文件) 当我在linux服务器(ubuntu)中使用curl命令时,我可以得到成功响应Java 我可以';nt使用pem在resttemplate中设置证书,java,spring,ssl,resttemplate,client-certificates,Java,Spring,Ssl,Resttemplate,Client Certificates,我的springboot项目有问题。 我必须向其他服务器发送rest调用(https:///....). 我还必须在java中使用证书密钥(.pem文件) 当我在linux服务器(ubuntu)中使用curl命令时,我可以得到成功响应 curl -X GET --cert <pem file path>:<password> https://<serverurl>:4443 curl-xget--cert:https://:4443 但我的问题是我必须在S
curl -X GET --cert <pem file path>:<password> https://<serverurl>:4443
curl-xget--cert:https://:4443
但我的问题是我必须在SpringBootJava项目中使用RestTemplate。
因此,我尝试配置一些步骤,但失败了
有人知道在resttemplate中使用配置证书(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));
}}
@配置
公共类RestTemplateConfig{
私有静态记录器Logger=LoggerFactory.getLogger(restemplateconfig.class);
@自动连线
私人环境署;
//.crt路径
@值(${cert.path}”)
私有字符串证书文件;
//.p12路径
@值(${bixby.reward.p12.path})
私有字符串p12文件;
//.jks径
@值(${http.client.ssl.trust store}”)
私有资源信任库;
//密码
@值(${http.client.ssl.trust-store-password}”)
私有字符[]信任存储密码;
@豆子
公共RestTemplate RestTemplate(){
PoollightTPClientConnectionManager cm=getConnectionManager(2000);
CloseableHttpClient httpClient=HttpClients.custom()
.setConnectionManager(cm)
.setProxy(getProxyHost())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
HttpComponents客户端HttpRequestFactory组件客户端HttpRequestFactory=新的HttpComponents客户端HttpRequestFactory();
组件客户端HttpRequestFactory.setHttpClient(httpClient);
componentsClientHttpRequestFactory.setConnectTimeout(常数.CONNECTION\u TIME\u OUT);
ComponentClientHttpRequestFactory.setReadTimeout(常数.READ\u TIME\u OUT);
RestTemplate RestTemplate=新的RestTemplate(ComponentClientHttpRequestFactory);
返回REST模板;
}
私有HttpHost getProxyHost(){
HttpHost proxyHost=null;
字符串httpProxy=env.getProperty(“http_proxy”);
if(httpProxy!=null){
试一试{
字符串host=null;
int端口=-1;
httpProxy=httpProxy.replace(“https://”和“”).replace(“http://”和“”);
字符串[]proxy=httpProxy.split(“:”);
主机=代理[0];
如果(proxy.length==1){
端口=80;
}否则{
port=Integer.parseInt(代理[1]);
}
proxyHost=新的HttpHost(主机、端口);
}捕获(例外e){
logger.error(“[隐式错误]RestTemplate代理设置错误”,e);
}
}
返回代理主机;
}
私有SSLConnectionSocketFactory getSSLSocketFactoryForNoVerification(){
SSLConnectionSocketFactory scsf=null;
试一试{
TrustStrategy acceptingTrustStrategy=(X509Certificate[]链,字符串authType)->true;
文件f=新文件(“”);
SSLContext SSLContext=SSLContexts.custom()
.loadTrustMaterial(空,acceptingTrustStrategy)
.build();
scsf=新的SSLConnectionSocketFactory(sslContext,新的NoopHostnameVerifier());
}捕获(例外e){
logger.error(“[隐式错误]RestTemplate ssl连接套接字工厂设置错误”,e);
}
返回scsf;
}
私有SSLSocketFactory getSSLSocketFactory(){
SSLContext SSLContext=null;
试一试{
InputStream certInputStream=新文件InputStream(certFile);
字节[]certAndKey=ByTestStreams.toByteArray(certInputStream);
byte[]certBytes=parseDERFromCert(certAndKey,“----开始证书----”,“----结束证书----”;
X509Certificate cert=generateCertificateFromDER(certBytes);
//私钥
KeyStore pkeyStore=KeyStore.getInstance(“PKCS12”);
load(新文件输入流(p12文件)、trustStorePassword.toCharray());
//“服务器”是别名
Key pvtKey=pkeyStore.getKey(“服务器”,trustStorePassword.tocharray());
java.security.cert.Certificate[]keychain=pkeyStore.getCertificateChain(“服务器”);
KeyStore KeyStore=KeyStore.getInstance(“JKS”);
keystore.load(null);
setCertificateEntry(“证书别名”,cert);
setKeyEntry(“密钥别名”,pvtKey,“changeit”.toCharArray(),keychain);
KeyManagerFactory kmf=KeyManagerFactory.getInstance(“SunX509”);
init(密钥库,“changeit.tocharray());
TrustStrategy acceptingTrustStrategy=(X509Certificate[]链,字符串authType)->true;
sslContext=SSLContexts.custom().loadTrustMaterial(密钥库,acceptingTrustStrategy.build();
KeyManager[]km=kmf.getKeyManager();
init(km,null,null);
}捕获(例外e){
logger.error(“[隐式错误]RestTemplate ssl连接套接字工厂设置错误”,e);
}
返回sslContext.getSocketFactory();
}
专用池TpClientConnectionManager getConnectionManager(int maxTotal){
SSLContext SSLContext;
注册表=空;
试一试{
sslContext=SSLContexts
.custom()
.loadTrustMaterial(trustStore.getFile(),
TrustStore(密码)
.build();
//因为只有我们自己的证书是可信的,所以主机名验证可能是安全的
HostnameVerifier HostnameVerifier=SSLConnectionSocketFactory.getDefaultHostnameVerifier();
SSLConnectionSocketFactory sslSocketFactory=新的SSLConnectionSocketFactory(sslContext,hostnameVerifier);//新的NoopHostnameVerifier();
registry=RegistryBuilder.create()
.register(“http”,新的PlainConnectionSocketFactory())
//.register(“https”,getSSLSocketFactoryForNoVerification())
//.register(“https”、新的SSLConnectionSocketFactory(getSSLSocketFactory()、新的NoopHostnameVerifier()))
.register(“https”,sslSocketFactory)
.build();
}捕获(例外e){
//托德