springboot 请求https

这两天研究了下springboot 请求https,记录一下遇到的问题及解决方案。

添加依赖

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

对于需要添加证书的请求:

添加证书

(一)证书的下载

先通过浏览器将未签名验证的证书保存到本地, 点击 不安全–> 证书–> 详细信息 --> 复制到文件 然后默认选择 起一个文件名 , 保存即可, 比如我将证书保存在了桌面 , 命名为 file.cer(名称自定义,cer格式)

(二)证书导入JDK

如何把上面那步的(file.cer)这个证书导入java中的cacerts证书库里?
如:我的 jdk安装这个目录在 C:\Program Files\Java\jdk1.8.0_191

开始 >> 运行 >> 输入cmd 进入dos命令行 >>
再用cd进入到C:\Program Files\Java\jdk1.8.0_191\jre\lib\security这个目录下
敲入如下命令回车执行
keytool -import -alias cacerts -keystore cacerts -file C:\Users\huihe10\Desktop\file.cer

你敲入changeit就行了,这java中cacerts证书库的默认密码
若是changeit不行就写 changeme 一般的 chageit 就可以了。

如果提示:“ 是否信任此证书?[ 否]:” ,那么请输入“y”
当出现:“证书已添加到密钥库中[ 正在存储cacerts] ”的时候,那么恭喜你已经添加成功。

tip:这个步骤也可参考连接: https://blog.csdn.net/liruiqing/article/details/80416740

(三)生成keystore文件

只将证书导入JDK就可以了吗? 我这里验证的是不可以的, 必须还要生成对应的 keystore文件

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

说明: 执行改命令时,进入证书所在的文件夹,我的是 C:\Users\huihe10\Desktop\file.cer
(若是提示权限不够 linux那就再加sudo , windows就以管理员的身份执行)
回车后又会让你输入密码 , 那么就还对应着输入 chageit 即可
执行完毕后会在当前路径下再产生一个xx.keystore文件.
xx:自定义,我这里叫file

项目中配置

  • 将上面上传的xx.keystore 文件文件复制到你的项目的类路径下(srv/main/resource下面)
  • 将下面的这个restTemplate的配置复制到你的项目中去,其中里面用到了一个httpConverter 这个是做json格式转换的, 和HTTPS没太大关系 , 若是不需要就将它以及相关代码删掉即可。
@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);
    	    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;
    }
}

测试

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration({"/static/applicationContext.xml"})
public class DemoApplicationTests {

    private static final Logger LOGGER = LoggerFactory.getLogger(DemoApplicationTests.class);

    @Autowired
    private RestTemplate restTemplate;

    @Test
    public void doHttps(){
        try {
            String url = "https://xxx.boshi.com.cn";
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
            HttpEntity requestEntity = new HttpEntity<>(headers);
            String responseBody = restTemplate.getForObject(url, String.class);
            System.out.println(responseBody);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

Tips

对于不需要添加证书的请求,可以用以下代码:

@Bean
    public RestTemplate restTemplate() {
        ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient());
        return new RestTemplate(requestFactory);
    }

    private HttpClient httpClient(){
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        connectionManager.setMaxTotal(200);
        connectionManager.setDefaultMaxPerRoute(100);
        connectionManager.setValidateAfterInactivity(2000);
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(65000) // 服务器返回数据(response)的时间,超时抛出read timeout
                .setConnectTimeout(5000) // 连接上服务器(握手成功)的时间,超时抛出connect timeout
                .setConnectionRequestTimeout(1000)// 从连接池中获取连接的超时时间,超时抛出ConnectionPoolTimeoutException
                .build();
        return HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setConnectionManager(connectionManager).build();
    }

如果要绕开证书信任,可以用以下代码:

@Bean
    public RestTemplate buildRestTemplate(*//*List<CustomHttpRequestInterceptor> interceptors*//*) throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setConnectionRequestTimeout(6500);
        factory.setConnectTimeout(6500);
        factory.setReadTimeout(5000);

        SSLContextBuilder builder = new SSLContextBuilder();
        builder.loadTrustMaterial(null, (X509Certificate[] x509Certificates, String s) -> true);
        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(builder.build(), new String[]{"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2"}, null, 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<ClientHttpRequestInterceptor> clientInterceptorList = new ArrayList<>();
        for (CustomHttpRequestInterceptor i : interceptors) {
            ClientHttpRequestInterceptor interceptor = i;
            clientInterceptorList.add(interceptor);
        }
        restTemplate.setInterceptors(clientInterceptorList);*//*

        return restTemplate;
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值