场景
restTemplate发送http请求时没问题,发送https请求时要求验证证书,造成请求失败。
解决方案
方案一 忽略证书验证
新建一个SSL类,代码:
public class SSL extends SimpleClientHttpRequestFactory {
@Override
protected void prepareConnection(HttpURLConnection connection, String httpMethod)
throws IOException {
if (connection instanceof HttpsURLConnection) {
prepareHttpsConnection((HttpsURLConnection) connection);
}
super.prepareConnection(connection, httpMethod);
}
private void prepareHttpsConnection(HttpsURLConnection connection) {
connection.setHostnameVerifier(new SkipHostnameVerifier());
try {
connection.setSSLSocketFactory(createSslSocketFactory());
}
catch (Exception ex) {
// Ignore
}
}
private SSLSocketFactory createSslSocketFactory() throws Exception {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[] { new SkipX509TrustManager() },
new SecureRandom());
return context.getSocketFactory();
}
private class SkipHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
}
private static class SkipX509TrustManager implements X509TrustManager {
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
}
}
Application或者Configuration类里面配置restTemplate:
@Bean
@Resource(name="simpleClientHttpRequestFactory") // 在多ClientHttpRequestFactory的时候指定用哪个
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SSL factory = new SSL();
factory.setReadTimeout(60000);
factory.setConnectTimeout(30000);//单位为ms
return factory;
}
这样就可以发送https请求了。
好处是代码相对简单,开发速度快。
缺点是不太安全。
方案二 添加证书列表
好处是更安全。
缺点是代码稍复杂,要多花点时间研究。
代码暂略。