Spring Boot SSL Client

I am new to Spring Boot. While I like it. I developed a demo SSL server that correctly handles mutual authentication of an X.509 certificate. Using the IE browser with self-signed client and server certificates, I checked that the demo rest web server is working correctly - both the server and the browser successfully exchange and verify each other's certificates.

I am having trouble finding an example SSL client that shows how to enable a client certificate and issue https. Does anyone have a simple client client example that shows how to consume my ssl server?

Regards, Steve Mansfield

+7
source share
6 answers

I could not get the above client represented by Andy to work. I kept getting errors saying that "localhost! = Clientname". Anyway, I got this to work correctly.

import java.io.IOException; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.URI; import org.apache.commons.httpclient.methods.GetMethod; public class SSLClient { static { System.setProperty("javax.net.ssl.trustStore","c:/apachekeys/client1.jks"); System.setProperty("javax.net.ssl.trustStorePassword", "password"); System.setProperty("javax.net.ssl.keyStore", "c:/apachekeys/client1.jks"); System.setProperty("javax.net.ssl.keyStorePassword", "password"); } public static void main(String[] args) throws HttpException, IOException { HttpClient client = new HttpClient(); GetMethod method = new GetMethod(); method.setURI(new URI("https://localhost:8443/restserver", false)); client.executeMethod(method); System.out.println(method.getResponseBodyAsString()); } } 
+6
source

Given that you are using Spring, here is an example that shows how to use the Spring RestTemplate and Apache HttpClient configured with the client certificate and trust the self-signed certificate from the server:

 KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(new FileInputStream(new File("keystore.jks")), "secret".toCharArray()); SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( new SSLContextBuilder() .loadTrustMaterial(null, new TrustSelfSignedStrategy()) .loadKeyMaterial(keyStore, "password".toCharArray()).build()); HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory).build(); ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory( httpClient); RestTemplate restTemplate = new RestTemplate(requestFactory); ResponseEntity<String> response = restTemplate.getForEntity( "https://localhost:8443", String.class); 
+10
source

The user1707141 example did not work for me, and skmansfield seems more likely to depend on specific files that are not consistent with Spring Boot / Maven. Also, Andy Wilkinson's answer uses the SSLConnectionSocketFactory constructor, which is deprecated in Apache httpclient 4.4+, and also seems rather complicated.

So, I created an example project that should show everything 100% understandable here: https://github.com/jonashackt/spring-boot-rest-clientcertificate

Besides the usual use of RestTemplate with @Autowired in your test class, be sure to configure RestTemplate as follows:

 package de.jonashackt.restexamples; import org.apache.http.client.HttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContextBuilder; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.util.ResourceUtils; import org.springframework.web.client.RestTemplate; import javax.net.ssl.SSLContext; @Configuration public class RestClientCertTestConfiguration { private String allPassword = "allpassword"; @Bean public RestTemplate restTemplate(RestTemplateBuilder builder) throws Exception { SSLContext sslContext = SSLContextBuilder .create() .loadKeyMaterial(ResourceUtils.getFile("classpath:keystore.jks"), allPassword.toCharArray(), allPassword.toCharArray()) .loadTrustMaterial(ResourceUtils.getFile("classpath:truststore.jks"), allPassword.toCharArray()) .build(); HttpClient client = HttpClients.custom() .setSSLContext(sslContext) .build(); return builder .requestFactory(new HttpComponentsClientHttpRequestFactory(client)) .build(); } } 
+3
source

I know it too late, but here is the code that works for me.

 @SpringBootApplication public class Application { private static final Logger log = LoggerFactory.getLogger(Application.class); public static void main(String args[]) { makeWebServiceCall(); } public static void makeWebServiceCall() { TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true; SSLContext sslContext; ResponseEntity<String> response = null; try { 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); StringBuffer plainCreds = new StringBuffer(); plainCreds.append("username"); plainCreds.append(":"); plainCreds.append("password"); byte[] plainCredsBytes = plainCreds.toString().getBytes(); byte[] base64CredsBytes = Base64.getEncoder().encode(plainCredsBytes); String userBase64Credentials = new String(base64CredsBytes); HttpHeaders headers = new HttpHeaders(); headers.add("Authorization", "Basic " + userBase64Credentials); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity entity = new HttpEntity<>(headers); String url = "https:restUrl"; response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class); if(response.getStatusCodeValue() == 200) { log.info("Success! Further processing based on the need"); } else { log.info("****************Status code received: " + response.getStatusCodeValue() + ".************************"); } } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) { log.error("Exception occured. Here are the exception details: ", e); } catch(HttpClientErrorException e) { if(e.getRawStatusCode() == 403) { log.info("****************Status code received: " + e.getRawStatusCode() + ". You do not have access to the requested resource.************************"); } else if(e.getRawStatusCode() == 404) { log.info("****************Status code received: " + e.getRawStatusCode() + ". Resource does not exist(or) the service is not up.************************"); } else if(e.getRawStatusCode() == 400) { log.info("****************Status code received: " + e.getRawStatusCode() + ". Bad Request.************************"); } else { log.info("****************Status code received: " + e.getRawStatusCode() + ".************************"); } log.info("****************Response body: " + e.getResponseBodyAsString() + "************************"); } } } 

Here is maven filed

 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.springframework</groupId> <artifactId>gs-consuming-rest</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.3</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.4.6</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> 

0
source

Another way to do it.

 @Configuration public class SampleSSLClient extends RestTemplate{ /** The key store password. */ private String keyStorePassword; /** The key store location. */ private String keyStoreLocation; /** The rest template. */ @Autowired private RestTemplate restTemplate; /** The http components client http request factory. */ private HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory; /** * Instantiates a new custom rest template. */ public CustomRestTemplate() { super(); } public CustomRestTemplate(RestTemplate restTemplate){ this.restTemplate = getRestTemplate(); } /** * Rest template. * * @return the rest template */ public RestTemplate getRestTemplate() { if (null == httpComponentsClientHttpRequestFactory) { httpComponentsClientHttpRequestFactory = loadCert(); restTemplate.setRequestFactory(httpComponentsClientHttpRequestFactory); } return restTemplate; } /** * Load cert. * * @return the http components client http request factory */ private HttpComponentsClientHttpRequestFactory loadCert() { try { char[] keypass = keyStorePassword.toCharArray(); SSLContext sslContext = SSLContextBuilder.create() .loadKeyMaterial(getkeyStore(keyStoreLocation, keypass), keypass) .loadTrustMaterial(null, new TrustSelfSignedStrategy()).build(); HttpClient client = HttpClients.custom().setSSLContext(sslContext).build(); httpComponentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(client); httpComponentsClientHttpRequestFactory.setConnectTimeout(5000); httpComponentsClientHttpRequestFactory.setReadTimeout(30000); } catch (Exception ex) { LOGGER.error(MessageFormat.format("Some Error", ex.getMessage()), ex); } return httpComponentsClientHttpRequestFactory; } /** * Key store. * * @param storePath the store path * @param password the password * @return the key store */ private KeyStore getkeyStore(String storePath, char[] password) { KeyStore keyStore; try { keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); File key = ResourceUtils.getFile(storePath); try (InputStream in = new FileInputStream(key)) { keyStore.load(in, password); } }catch (Exception ex) { LOGGER.error(MessageFormat.format("Some Error", ex.getMessage()), ex); } return keyStore; } /** * Sets the key store password. * * @param keyStorePassword the new key store password */ public void setKeyStorePassword(String keyStorePassword) { this.keyStorePassword = keyStorePassword; } /** * Sets the key store location. * * @param keyStoreLocation the new key store location */ public void setKeyStoreLocation(String keyStoreLocation) { this.keyStoreLocation = keyStoreLocation; } /** * Sets the rest template. * * @param restTemplate the new rest template */ public void setRestTemplate(RestTemplate restTemplate) { this.restTemplate = restTemplate; } 
0
source

This worked for me:

 TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true; javax.net.ssl.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); 
-3
source

Source: https://habr.com/ru/post/988885/


All Articles