Spring-BootSpring Boot

RestTemplate设置headers,访问https实现s

2017-09-15  本文已影响8859人  _奔波儿灞_

在上一篇springboot学习记录之RestTemplate中,我们知道了:

  1. 如何创建RestTemplate实例
  2. 如何通过spring管理RestTemplate
  3. 如何使用RestTemplate。

在这篇文章中我们将重点说下如何来用https实现ssl请求。

应用场景:微信支付之企业付款接口

文档中提到:请求需要双向证书。 详见证书使用

微信给我们颁发了pfx证书:apiclient_cert.p12

这个时候我们不能像往常一样直接通过

RestTemplate restTemplate = new RestTemplate();
restTemplate.postForObject(url,T.class);

来实现请求并获得结果,我们需要设置ssl相关信息及参数。

微信官方实例:

这个版本是基于httpcomponents 4.3.1 。pom 文件如下:


        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.3.1</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

    private String ssl(String url, String data) {

        //HttpsRequest
        StringBuffer message = new StringBuffer();
        try {
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            FileInputStream instream = new FileInputStream(new File("证书地址"));
            keyStore.load(instream, "支付商户号".toCharArray());
            // Trust own CA and all self-signed certs
            SSLContext sslcontext = SSLContexts.custom()
                    .loadKeyMaterial(keyStore, "支付商户号".toCharArray())
                    .build();
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[]{"TLSv1"},
                    null,
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            CloseableHttpClient httpclient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .build();
            HttpPost httpost = new HttpPost(url);

            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
           

            CloseableHttpResponse response = httpclient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();

                if (entity != null) {
                
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
                    String text;
                    while ((text = bufferedReader.readLine()) != null) {
                        message.append(text);
                    }
                }
                EntityUtils.consume(entity);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                response.close();
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        return message.toString();
    }

那么我们如何用RestTemplate 来实现呢:
我这边使用的是httpcomponents 最新版4.5.3:

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

构建httpclient参数的时候有些和4.3.1不同


    public String TransferRestTemplate(String url,String data) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        FileInputStream instream = new FileInputStream(new File(merchantInfo.getPfx()));
        keyStore.load(instream, merchantInfo.getId().toCharArray());
        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContextBuilder.create()
                .loadKeyMaterial(keyStore, merchantInfo.getId().toCharArray())
                .build();
        // Allow TLSv1 protocol only
        HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,  new String[]{"TLSv1"},
                null,hostnameVerifier);

        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();

        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpclient);
        RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.add("Connection", "keep-alive");
        requestHeaders.add("Accept", "*/*");
        requestHeaders.add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        requestHeaders.add("Host", "api.mch.weixin.qq.com");
        requestHeaders.add("X-Requested-With", "XMLHttpRequest");
        requestHeaders.add("Cache-Control", "max-age=0");
        requestHeaders.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");

        org.springframework.http.HttpEntity<String> requestEntity =
                new  org.springframework.http.HttpEntity(new StringEntity(data, "UTF-8"),requestHeaders);

        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
        String sttr = response.getBody();
        return sttr;

    }

注意:此处HttpEntity 和上面的微信实例的org.apache.http.HttpEntity 是不同的。

这样我们就实现了ssl请求了。

上一篇下一篇

猜你喜欢

热点阅读