2015-06-11 2 views
6

Я новичок в Spring Boot. Пока мне это нравится. Я разработал демонстрационный SSL-сервер, который правильно обрабатывает взаимную аутентификацию сертификата X.509. Используя браузер IE с самозаверяющим клиентом & сертификаты сервера, я протестировал, что веб-сервер демонстрационного отдыха работает правильно - и сервер, и браузер успешно обмениваются и проверяют сертификаты друг друга.Spring Boot SSL Client

У меня возникли проблемы с поиском примера клиента SSL, который показывает, как включить сертификат клиента и выдать https. У кого-нибудь есть простой пример клиента клиента, который показывает, как потреблять мой сервер ssl?

С наилучшими пожеланиями, Стив Мэнсфилд

+0

Что клиент сделать йо Вы имеете в виду? Java (с весной)? Или что-то другое? – koe

+0

Весна была бы лучше, но Java тоже хорошо. – skmansfield

ответ

6

Я не мог получить вышеуказанный клиент, представленный Энди для работы. Я продолжал получать ошибки, говоря, что «localhost! = Clientname». В любом случае, я получил это, чтобы работать правильно.

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()); 

    } 

} 
9

Учитывая, что вы используете Spring, вот пример, который показывает, как использовать Spring, RestTemplate и апач HttpClient сконфигурирован с сертификатом клиента и доверять самостоятельно подписанный сертификат от сервер:

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); 
+0

Компилятор лает на SSLConnectionSocketFactory. Я играл с ним пару часов, но не повезло. Можете ли вы взглянуть и исправить? – skmansfield

+0

Еще один вопрос о коде. у вас есть «секрет» в хранилище ключей, а затем «пароль» в файле loadkey. Что секрет? – skmansfield

+0

Я не думаю, что для 'SSLConnectionSocketFactory' есть что-то исправлять. Вот его [javadoc] (http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ssl/SSLConnectionSocketFactory.html), если это помогает. 'secret' - пароль для всего хранилища ключей. 'password' - пароль для ключа в хранилище ключей. –

0

Я знаю его слишком поздно, но вот код, который работает для меня.

@SpringBootApplication 
 
public class Application { 
 

 
\t private static final Logger log = LoggerFactory.getLogger(Application.class); 
 

 
\t public static void main(String args[]) { 
 

 
\t \t \t makeWebServiceCall(); 
 

 
\t } 
 
\t 
 
\t public static void makeWebServiceCall() { 
 
\t \t TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true; 
 

 
\t \t SSLContext sslContext; 
 
\t \t ResponseEntity<String> response = null; 
 
\t \t try { 
 
\t \t \t sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy) 
 
\t \t \t \t \t .build(); 
 

 
\t \t \t SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext); 
 

 
\t \t \t CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build(); 
 

 
\t \t \t HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); 
 

 
\t \t \t requestFactory.setHttpClient(httpClient); 
 

 
\t \t \t RestTemplate restTemplate = new RestTemplate(requestFactory); 
 
\t \t \t 
 
\t \t \t StringBuffer plainCreds = new StringBuffer(); 
 
\t \t \t plainCreds.append("username"); 
 
\t \t \t plainCreds.append(":"); 
 
\t \t \t plainCreds.append("password"); 
 
\t \t \t byte[] plainCredsBytes = plainCreds.toString().getBytes(); 
 
\t \t \t byte[] base64CredsBytes = Base64.getEncoder().encode(plainCredsBytes); 
 
\t \t \t String userBase64Credentials = new String(base64CredsBytes); 
 
\t \t \t 
 

 
\t \t \t HttpHeaders headers = new HttpHeaders(); 
 
\t \t \t headers.add("Authorization", "Basic " + userBase64Credentials); 
 
\t \t \t headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); 
 
\t \t \t headers.setContentType(MediaType.APPLICATION_JSON); 
 

 
\t \t \t HttpEntity entity = new HttpEntity<>(headers); 
 

 
\t \t \t String url = "https:restUrl"; 
 
\t \t \t 
 
\t \t \t response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class); 
 
\t \t \t 
 
\t \t \t if(response.getStatusCodeValue() == 200) { 
 
\t \t \t \t log.info("Success! Further processing based on the need"); 
 
\t \t \t } else { 
 
\t \t \t \t log.info("****************Status code received: " + response.getStatusCodeValue() + ".************************"); 
 
\t \t \t } 
 

 
\t \t } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) { 
 
\t \t \t log.error("Exception occured. Here are the exception details: ", e); 
 
\t \t } catch(HttpClientErrorException e) { 
 
\t \t \t if(e.getRawStatusCode() == 403) { 
 
\t \t \t \t log.info("****************Status code received: " + e.getRawStatusCode() + ". You do not have access to the requested resource.************************"); 
 
\t \t \t \t 
 
\t \t \t } else if(e.getRawStatusCode() == 404) { 
 
\t \t \t \t log.info("****************Status code received: " + e.getRawStatusCode() + ". Resource does not exist(or) the service is not up.************************"); 
 

 
\t \t \t } else if(e.getRawStatusCode() == 400) { 
 
\t \t \t \t log.info("****************Status code received: " + e.getRawStatusCode() + ". Bad Request.************************"); 
 

 
\t \t \t } else { 
 
\t \t \t \t log.info("****************Status code received: " + e.getRawStatusCode() + ".************************"); 
 
\t \t \t \t 
 
\t \t \t } 
 

 
      log.info("****************Response body: " + e.getResponseBodyAsString() + "************************"); 
 
\t \t } 
 
\t } 
 
}

Вот Maven подал

<?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> 

1

Пример user1707141 didn't работы для меня и skmansfield кажется скорее в зависимости от конкретных файлов, которые Арен Соглашение с Spring Boot/Maven. Также ответ Andy Wilkinson использует конструктор SSLConnectionSocketFactory, который устарел в Apache httpclient 4.4+, а также кажется довольно сложным.

Так что я создал пример проект, который должен показать все 100% понятного здесь: https://github.com/jonashackt/spring-boot-rest-clientcertificate

Помимо обычного использования RestTemplate с @Autowired в вашем TestClass, убедитесь, что настроить RestTemplate так:

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(); 
    } 
} 
-2

Это работает для меня:

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); 
Смежные вопросы