Oto kod, który przedstawi ogólny pomysł.
Musisz utworzyć niestandardowy ClientHttpRequestFactory
, aby zaufać certyfikatowi. Wygląda to tak:
final ClientHttpRequestFactory clientHttpRequestFactory =
new MyCustomClientHttpRequestFactory(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER, serverInfo);
restTemplate.setRequestFactory(clientHttpRequestFactory);
Jest to realizacja dla MyCustomClientHttpRequestFactory
:
public class MyCustomClientHttpRequestFactory extends SimpleClientHttpRequestFactory {
private final HostnameVerifier hostNameVerifier;
private final ServerInfo serverInfo;
public MyCustomClientHttpRequestFactory (final HostnameVerifier hostNameVerifier,
final ServerInfo serverInfo) {
this.hostNameVerifier = hostNameVerifier;
this.serverInfo = serverInfo;
}
@Override
protected void prepareConnection(final HttpURLConnection connection, final String httpMethod)
throws IOException {
if (connection instanceof HttpsURLConnection) {
((HttpsURLConnection) connection).setHostnameVerifier(hostNameVerifier);
((HttpsURLConnection) connection).setSSLSocketFactory(initSSLContext()
.getSocketFactory());
}
super.prepareConnection(connection, httpMethod);
}
private SSLContext initSSLContext() {
try {
System.setProperty("https.protocols", "TLSv1");
// Set ssl trust manager. Verify against our server thumbprint
final SSLContext ctx = SSLContext.getInstance("TLSv1");
final SslThumbprintVerifier verifier = new SslThumbprintVerifier(serverInfo);
final ThumbprintTrustManager thumbPrintTrustManager =
new ThumbprintTrustManager(null, verifier);
ctx.init(null, new TrustManager[] { thumbPrintTrustManager }, null);
return ctx;
} catch (final Exception ex) {
LOGGER.error(
"An exception was thrown while trying to initialize HTTP security manager.", ex);
return null;
}
}
W tym przypadku moja serverInfo
obiekt zawiera odcisk palca serwera. Musisz zaimplementować interfejs TrustManager
, aby uzyskać z SslThumbprintVerifier
lub dowolną inną metodę, którą chcesz zweryfikować (możesz także zawsze zwrócić true
).
Wartość org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
zezwala na wszystkie nazwy hostów. Jeśli musisz zweryfikować nazwę hosta, , musisz wdrożyć ją inaczej.
Nie mam pewności co do użytkownika i hasła oraz sposobu jego wdrożenia. Często należy dodać nagłówek do restTemplate
o nazwie Authorization
o wartości podobnej do tej: Base: <encoded user+password>
. Kodowana user+password
musi być Base64
.
Dużo mojego kodu został wzięty stąd: http://stackoverflow.com/questions/15544116/sslhandshakeexception -received-fatal-alert-handshake-failure-when-setting-ciph – Avi
Wygląda całkiem czysto, z wyjątkiem "System.setProperty (" https.protocols "," TLSv1 ");" linia. Czy istnieje sposób bez ustawiania pewnych rzeczy na poziomie systemu? Mam podobny problem i chcę wyizolować problem związany z certyfikatem tylko z jednym komponentem bean. – Ruslan
@Ruslan - Wow, zabrałeś mnie z powrotem z tą odpowiedzią.Niestety, było to zbyt dawno temu i od tego czasu zmieniłem już dwa miejsca pracy, więc nie mam kodu źródłowego i nie mogłem sobie przypomnieć, dlaczego robiłem rzeczy tak, jak ja. Jestem prawie pewny, że było na to sposób, spróbuję sprawdzić, czy mogę znaleźć inny sposób, a jeśli tak, to go tutaj zamieściłem. – Avi