可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am having two Spring based web apps A and B, on two different machines.
I want to make a https call from web app A to web app B, however I am using a self-signed certificate in Machine B. So my HTTPS request fails.
How can I disable https certificate validation when using RestTemplate in Spring ? I want to disable validation because both web app A and B are within the internal network, but data transfer has to happen over HTTPS
回答1:
What you need to add is a custom HostnameVerifier
class bypasses certificate verification and returns true
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } });
This needs to be placed appropriately in your code.
回答2:
@Bean public RestTemplate restTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true; SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom() .loadTrustMaterial(null, acceptingTrustStrategy) .build(); SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext); CloseableHttpClient httpClient = HttpClients.custom() .setSSLSocketFactory(csf) .build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); requestFactory.setHttpClient(httpClient); RestTemplate restTemplate = new RestTemplate(requestFactory); return restTemplate; }
回答3:
Essentially two things you need to do are use a custom TrustStrategy that trusts all certs, and also use NoopHostnameVerifier() to disable hostname verification. Here is the code, with all the relevant imports:
import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLContext; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; public RestTemplate getRestTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { TrustStrategy acceptingTrustStrategy = new TrustStrategy() { @Override public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { return true; } }; SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build(); SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier()); CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); requestFactory.setHttpClient(httpClient); RestTemplate restTemplate = new RestTemplate(requestFactory); return restTemplate; }
回答4:
Add my response with cookie : public static void main(String[] args) { MultiValueMap params = new LinkedMultiValueMap(); params.add("username", testUser); params.add("password", testPass); NullHostnameVerifier verifier = new NullHostnameVerifier(); MySimpleClientHttpRequestFactory requestFactory = new MySimpleClientHttpRequestFactory(verifier , rememberMeCookie); ResponseEntity response = restTemplate.postForEntity(appUrl + "/login", params, String.class); HttpHeaders headers = response.getHeaders(); String cookieResponse = headers.getFirst("Set-Cookie"); String[] cookieParts = cookieResponse.split(";"); rememberMeCookie = cookieParts[0]; cookie.setCookie(rememberMeCookie); requestFactory = new MySimpleClientHttpRequestFactory(verifier,cookie.getCookie()); restTemplate.setRequestFactory(requestFactory); } public class MySimpleClientHttpRequestFactory extends SimpleClientHttpRequestFactory { private final HostnameVerifier verifier; private final String cookie; public MySimpleClientHttpRequestFactory(HostnameVerifier verifier ,String cookie) { this.verifier = verifier; this.cookie = cookie; } @Override protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException { if (connection instanceof HttpsURLConnection) { ((HttpsURLConnection) connection).setHostnameVerifier(verifier); ((HttpsURLConnection) connection).setSSLSocketFactory(trustSelfSignedSSL().getSocketFactory()); ((HttpsURLConnection) connection).setAllowUserInteraction(true); String rememberMeCookie = cookie == null ? "" : cookie; ((HttpsURLConnection) connection).setRequestProperty("Cookie", rememberMeCookie); } super.prepareConnection(connection, httpMethod); } public SSLContext trustSelfSignedSSL() { try { SSLContext ctx = SSLContext.getInstance("TLS"); X509TrustManager tm = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { } public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }; ctx.init(null, new TrustManager[] { tm }, null); SSLContext.setDefault(ctx); return ctx; } catch (Exception ex) { ex.printStackTrace(); } return null; } } public class NullHostnameVerifier implements HostnameVerifier { public boolean verify(String hostname, SSLSession session) { return true; } }
回答5:
You can use this with HTTPClient API.
public RestTemplate getRestTemplateBypassingHostNameVerifcation() { CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); requestFactory.setHttpClient(httpClient); return new RestTemplate(requestFactory); }