RestTemplate添加HTTPS證書全過程解析

RestTemplate添加HTTPS證書

證書的下載

先通過瀏覽器將未簽名驗證的證書保存到本地, 點擊 不安全–> 證書–> 詳細信息 –> 復制到文件 然後默認選擇 起一個文件名 , 保存即可, 比如我將證書保存在瞭桌面 , 命名為 xx.cer

證書導入JDK

若是想要在項目中用到證書 , 需要先將證書導入到JDK的證書管理裡面, 導入命令如下:

keytool -import -noprompt -trustcacerts -alias xx -keystore /home/oracle/jdk1.8.0_181/jre/lib/security/cacerts -file xx.cer

對上面的命令做一個解釋 此命令是在linux服務器內執行的 , 在執行這個命令的時候就在證書所在的文件夾下打開終端, 然後命名一下別名 , 別名最好和證書名稱一致 , 如上, 都叫xx , 另外將上面命令中的JDK路徑換成你的實際路徑即可

上面命令輸入完畢後回車 , 會讓你寫密碼啥的 , 就寫 changeit 若是changeit不行就寫 changeme 一般的 chageit 就可以瞭

生成keystore文件

隻將證書導入JDK就可以瞭嗎? 我這裡驗證的是不可以的, 必須還要生成對應的 keystore文件

keystore文件生成命令: keytool -import -file xx.cer -keystore xx.keystore

對上面的命令做一個解釋 , 該命令也是在linux下執行的 ,當然windows下也可以的 , 執行的時候也是在證書所在文件夾進行的 , 若是提示權限不夠 那就再加sudo , windows就以管理員的身份執行

回車後又會讓你輸入密碼 , 那麼就還對應著輸入 chageit 即可

執行完畢後會在當前路徑下再產生一個xx.keystore文件

項目中配置

將上面上傳的xx.keystore 文件文件復制到你的項目的類路徑下

將下面的這個restTemplate的配置復制到你的項目中去,其中裡面用到瞭一個httpConverter 這個是做json格式轉換的, 和HTTPS沒太大關系 , 若是不需要就將它以及相關代碼刪掉即可

package com.abc.air.config;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
/**
 * Created by ZhaoTengchao on 2019/4/12.
 */
@Configuration
public class RestTemplateConfig {
    @Autowired
    private FastJsonHttpMessageConverter httpMessageConverter;
    @Bean
    RestTemplate restTemplate() throws Exception {
    	HttpComponentsClientHttpRequestFactory factory = new                                                    
    	        HttpComponentsClientHttpRequestFactory();
    	    factory.setConnectionRequestTimeout(5 * 60 * 1000);
    	    factory.setConnectTimeout(5 * 60 * 1000);
    	    factory.setReadTimeout(5 * 60 * 1000);
    	    // https
    	    SSLContextBuilder builder = new SSLContextBuilder();
    	    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    	    ClassPathResource resource = new ClassPathResource("nonghang.keystore");
    	    InputStream inputStream = resource.getInputStream();
    	    keyStore.load(inputStream, null);
    	    SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(builder.build(), NoopHostnameVerifier.INSTANCE);
    	    Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
    	            .register("http", new PlainConnectionSocketFactory())
    	            .register("https", socketFactory).build();
    	    PoolingHttpClientConnectionManager phccm = new PoolingHttpClientConnectionManager(registry);
    	    phccm.setMaxTotal(200);
    	    CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory).setConnectionManager(phccm).setConnectionManagerShared(true).build();
    	    factory.setHttpClient(httpClient);
    	    RestTemplate restTemplate = new RestTemplate(factory);
    	    List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
            ArrayList<HttpMessageConverter<?>> convertersValid = new ArrayList<>();
            for (HttpMessageConverter<?> converter : converters) {
                if (converter instanceof MappingJackson2HttpMessageConverter ||
                    converter instanceof MappingJackson2XmlHttpMessageConverter) {
                    continue;
                }
                convertersValid.add(converter);
            }
            convertersValid.add(httpMessageConverter);
            restTemplate.setMessageConverters(convertersValid);
    	    inputStream.close();
        return restTemplate;
    }
}

到此配置完畢!

RestTemplate訪問HTTPS

本文簡述一下怎麼使用restTemplate來訪問https。

maven

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.3</version>
        </dependency>

這裡使用httpclient的factory

配置

    @Bean
    public RestTemplate restTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
        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);
        return restTemplate;
    }

驗證

    @Test
    public void testHttps(){
        String url = "https://free-api.heweather.com/v5/forecast?city=CN101080101&key=5c043b56de9f4371b0c7f8bee8f5b75e";
        String resp = restTemplate.getForObject(url, String.class);
        System.out.println(resp);
    }

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: