前置条件
需要Keystore文件(client.jks)和对应密码
需要Truststore文件(client_truststore.jks)和对应密码
1. 生成客户端的RestTemplate配置对象
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.security.*;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
@Configuration
public class SslConfig {
private static final String KEY_STORE_TYPE = "JKS";
private static final String TRUST_STORE_TYPE = "JKS";
@Bean
public RestTemplate restTemplate() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException, UnrecoverableKeyException {
KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
FileInputStream fis = null;
try {
fis = new FileInputStream("D:\\ssl\\ca0823\\client.jks");
keyStore.load(fis, "passwd".toCharArray());
fis.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
KeyStore trustStore = KeyStore.getInstance(TRUST_STORE_TYPE);
try {
fis = new FileInputStream("D:\\ssl\\ca0823\\client_truststore.jks");
trustStore.load(fis, "changeit".toCharArray());
fis.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
// Set up a trust manager that trusts the certificates in the truststore.
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
// Set up key manager to use our keypair.
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "passwd".toCharArray());
// Create an SSL context that uses our key manager and trust manager.
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLContext(sslContext)
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(requestFactory);
}
}
2. 生成HttpClient对象&发送请求
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class HttpClientService {
private final RestTemplate restTemplate;
@Autowired
public HttpClientService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public String sendPostRequest(String request) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity<String> entity = new HttpEntity<>(request, headers);
try {
return restTemplate.postForObject("https://10.2.2.183:7777/", entity, String.class);
} catch (Exception e) {
// 处理异常
e.printStackTrace();
return "Error: " + e.getMessage();
}
}
}
3. 证书调试
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.scheduling.annotation.EnableAsync;
@EnableAutoConfiguration
@SpringBootApplication
@EnableAsync
public class MainApplication {
public static void main(String[] arg0){
System.setProperty("javax.net.debug", "all");
new SpringApplicationBuilder(MainApplication.class)
.web(WebApplicationType.NONE) // 关闭Web支持
.run(arg0);
}
}
设置 System.setProperty("javax.net.debug", "all"); 的作用是开启 Java 网络通信库的调试信息输出。具体来说:
"javax.net.debug" 是一个系统属性,用于控制 SSL/TLS 连接的调试输出。
"all" 表示开启所有级别的调试信息,包括握手详情、记录协议详情等。
当设置了 "javax.net.debug=all" 之后,程序在运行过程中会输出大量的 SSL/TLS 相关的日志信息,这对于调试网络连接问题和安全协议相关的问题非常有帮助。这些日志通常会被输出到标准错误流(stderr)。
需要注意的是,由于输出的信息量很大,且可能包含敏感数据(如密钥信息),因此在生产环境中不建议开启此调试选项。它主要用于开发和测试阶段。