web-dev-qa-db-ja.com

Spring Boot SSLクライアント

Spring Bootは初めてです。これまでのところ、楽しんでいます。相互X.509証明書認証を正しく処理するデモSSLレストWebサーバーを開発しました。 IEブラウザと自己署名クライアントおよびサーバー証明書を使用して、デモレストWebサーバーが正常に機能していることをテストしました。サーバーとブラウザーの両方が、相互に証明書を正常に交換および検証しています。

クライアント証明書を含めてhttpsを発行する方法を示すSSLクライアントの例を見つけるのに問題があります。誰かが私のsslサーバーを使用する方法を示す簡単なRESTクライアントの例を持っていますか?

宜しくお願いします、Steve Mansfield

9
skmansfield

アンディから提出された上記のクライアントを機能させることができませんでした。 「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());

     }

 }
7
skmansfield

Springを使用している場合、クライアント証明書で構成されたSpringのRestTemplateおよびApacheの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);
12
Andy Wilkinson

ser1707141 の例は私にとっては機能せず、 skmansfield は特定のファイルに依存しているようですが、Spring Boot/Mavenの規約ではありません。また、 Andy Wilkinson の回答では、SSLConnectionSocketFactoryコンストラクタを使用しています。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();
    }
}
8
jonashackt

手遅れだとは思いますが、これが私のために働くコードです。

@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() + "************************");
                }
        }
 }

ここに提出されたメイブンです

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

これを行う別の方法。 keyStoreLocationとkeyStorePasswordの値を挿入します

@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