プログラミング逆引き辞典

~ 多言語対応のプログラミングレシピ ~

SpringBoot SSL/TLS接続時の証明書スキップ設定

自己証明書(オレオレ証明書)を生成してサーバー側に設定し、HTTPS接続する方法は下記で説明したとおり
 
 
SpringBoot SSL/TLS接続設定
 
 
Javaでは証明書とホストの検証を行っている為、クライアント側にも証明書の格納が必要となる
しかも自己証明書ではエラーとなってしまう
 
開発環境で正式に証明書を発行するというのはあまり現実的ではないので、今回はその証明書をスキップする方法を解説する
 
 

【開発の手順】

①Map型のレスポンスを返すAPIを作成(HTTPSで接続)
 
②リクエスト用のプロジェクトを作成し、証明書スキップ設定を記述
 
③②のプロジェクトを完成させる
 
④①のAPIのJarを作成する
 
⑤仮想サーバーを立ち上げ、デプロイ
 
⑥動作確認
 
★証明書スキップのメイン部分は手順②
その他は参考程度に見るだけも良い

 
 


以下、作成手順 
 

①Map型のレスポンスを返すAPIを作成(HTTPSで接続)

 
※作成方法は下記を参考にkeytoolコマンドで秘密鍵・公開鍵の生成、keystoreフォルダに格納する
また、application.propertiesにHTTPS有効化の設定を記述する
 
SpringBoot SSL/TLS接続設定
 
 
今回はシンプルにMap型インスタンスを返すAPIを作成
 
・ResponseController.java
パス:[メインパッケージ]/api/ResponseController.java

package com.example.api;

import java.util.HashMap;
import java.util.Map;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ResponseController {
    @GetMapping
    Map<Integer, String> responseMap() {
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "ryotsu");
        return map;
    }
}

 
 


②リクエスト用のプロジェクトを作成し、証明書スキップ設定を記述

 
HTTPクライアントのライブラリ使用できるようにする為に、「build.gradle」の「dependencies」ブロックに下記を追記

implementation 'org.apache.httpcomponents:httpclient:4.5.12'

 
 
configパケージを作成し、その直下に証明書スキップ設定クラスとなる「RestTemplateConfig.java」を作成する
 
・RestTemplateConfig.java
パス:[メインパッケージ]/config/RestTemplateConfig.java

package com.example.config;

import javax.net.ssl.SSLContext;

import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate() throws Exception {
        SSLContext sslContext = SSLContexts.custom()
                .loadTrustMaterial(new TrustSelfSignedStrategy()).build(); //TrustSelfSignedStrategyで自己署名証明書を許可する設定

        CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLContext(sslContext)
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) //ホスト名の検証しない設定
                .build();

        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        RestTemplate restTemplate = new RestTemplate(requestFactory);
        ((HttpComponentsClientHttpRequestFactory) restTemplate
                .getRequestFactory()).setHttpClient(httpClient); //RestTemplateで使うhttpClientを自己署名証明書対応されたClientに差し替え
        return restTemplate;
    }
}

 

【ポイント】

・@Configuration付与

Configurationアノテーションで設定クラスに指定する
これによりプロジェクトが起動した際にこのクラスが読み込まれるようになる
 

・@Bean付与

Beanアノテーションで「restTemplate」というBeanをDIコンテナに格納する
※メソッド名がBean名になる
 

・その他はソース内のコメントのとおり

 
 


③②のプロジェクトを完成させる

※①のAPIにリクエストを送り、レスポンスを受け取る
 
・RequestController.java
パス:[メインパッケージ]/rest/RequestController.java
 

package com.example.rest;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class RequestController {
    //開発の手順②で作成したBean(restTemplate)のインスタンスを取得
    @Autowired
    RestTemplate restTemplate;

    @GetMapping
    Map<?, ?> index() {
        //開発の手順①で作成したAPIのURL
        String url = "https://192.168.33.10:8443";

        @SuppressWarnings("rawtypes")
        ResponseEntity<Map> response = null;

        try {
            //APIにリクエストをGET送信
            response = restTemplate.getForEntity(url, Map.class);

            //リクエストがエラーの場合
            if (response.getStatusCodeValue() != 200) {
                HttpStatus httpStatus = response.getStatusCode();
                //エラー理由を取得
                String errReason = httpStatus.getReasonPhrase();
                //HTTPステータスコードを出力
                System.out.println(response.getStatusCodeValue());
                //エラー理由を出力
                System.out.println(errReason);
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.out.println(e.getCause());
        }

        //レスポンスが無い場合は画面に{"error", "no data"}と表示
        if (response == null) {
            Map<String, String> map = new HashMap<>();
            map.put("error", "no data");
            return map;
        }

        //正常にレスポンスが返ってきた場合は{"1":"ryotsu"}が表示される
        //※開発の手順①で作成したAPIのレスポンス結果
        return response.getBody();
    }
}

 
 


④①のAPIのJarを作成する

下記を参考にJarを作成
 
Gradle Jarの作成・実行
 
 


⑤仮想サーバーを立ち上げ、デプロイ

 
仮想サーバーを設定していない場合は下記を参考にすると良い
但し時間がかかるので余裕がある時に実施をおすすめする
 
ローカル開発環境構築(Windows)
 
※【⑩「Tera Term」で下記コマンドを実行して必要なアプリケーションをインストール】以降の設定は不要
 
 
 
更にJavaの設定が必要なので下記を参考に設定する
 
CentOS OpneJDK11のインストール方法
 
 
 
④で作成したJarをWinSCPなどの転送ツールでデプロイする

 
 
 
下記コマンドでJarを起動

java -jar [Jar名]

 

 
 


⑥動作確認

③で作成したリクエスト用のプロジェクトを起動して下記のように表示されることを確認