spring boot 使用RestTemplate信任所有https请求

3 篇文章 1 订阅
2 篇文章 0 订阅

RestTemplate在访问https资源时,出现报错
java.security.cert.CertificateException: No subject alternative names matching IP address ******* found; 

该问题主要是由于https请求时需要服务侧提供的证书认证,如果没有证书的话,可通过以下方法来信任请求:

一、通过CloseableHttpClient来信任所有https的请求(绕过证书认证)

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.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class HttpClientUtils {

    /**
     * CloseableHttpClient 信任所有https请求
     *
     * @return
     * @throws KeyStoreException
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    public static CloseableHttpClient acceptsUntrustedCertsHttpClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        HttpClientBuilder b = HttpClientBuilder.create();

        // 设置信任所有证书
        SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                return true;
            }
        }).build();
        b.setSSLContext(sslContext);

        HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;

        SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", sslSocketFactory)
                .build();

        PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        connMgr.setMaxTotal(200);
        connMgr.setDefaultMaxPerRoute(100);
        b.setConnectionManager(connMgr);

        CloseableHttpClient client = b.build();

        return client;
    }

}

二、 配置RestTemplate实例

import com.eastcom.intsight.fault.intellect.collect.util.HttpClientUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

    @Bean(name = "restTemplate")
    public RestTemplate httpsRestTemplate(HttpComponentsClientHttpRequestFactory httpsFactory){
        RestTemplate restTemplate = new RestTemplate(httpsFactory);
        restTemplate.setErrorHandler(new ResponseErrorHandler() {
            @Override
            public boolean hasError(ClientHttpResponse clientHttpResponse) {
                return false;
            }

            @Override
            public void handleError(ClientHttpResponse clientHttpResponse) {
                //默认处理非200的返回,会抛异常
            }
        });
        return restTemplate;
    }

    @Bean(name = "httpsFactory")
    public HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory() throws Exception{
        CloseableHttpClient httpClient = HttpClientUtils.acceptsUntrustedCertsHttpClient();
        HttpComponentsClientHttpRequestFactory httpsFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
        httpsFactory.setReadTimeout(2000);
        httpsFactory.setConnectTimeout(2000);
        return httpsFactory;
    }

}

三、 附上自己封装的RestTemplate工具类

import com.*.enums.BizExceptionCodeEnum;
import com.*.enums.ResultCodeEnum;
import com.*.exception.BizException;
import com.*.model.Result;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Map;

@Service
@Slf4j
public class InvokingService {

    @Resource(name = "restTemplate")
    private RestTemplate restTemplate;

    /**
     * 服务调用,返回响应Body
     *
     * @param url
     * @param type
     * @param paramType 参数类型,若是post请求,且参数类型为'@RequestBody'时,需特殊处理
     * @param headerMap 参数类型,若是post请求,且参数类型为'@RequestBody'时,需特殊处理
     * @param paramMap  参数类型为'@RequestBody'时,参数Map中只放一个随意key即可,值为JSON字符串参数
     * @return
     */
    public String invServiceForResultData(String url, String type, String paramType, Map<String, String> headerMap, Map<String, String> paramMap) {
        try {
            String resultObj = "";
            HttpEntity requestEntity = buildRequestEntity(paramType, headerMap, paramMap);
            if ("GET".equalsIgnoreCase(type)) {
                resultObj = restTemplate.getForObject(url, String.class);
            } else if ("POST".equalsIgnoreCase(type)) {
                resultObj = restTemplate.postForObject(url, requestEntity, String.class);
            } else if ("PUT".equalsIgnoreCase(type) || "DELETE".equalsIgnoreCase(type)) {
                ResponseEntity<String> responseEntity = restTemplate.exchange(url, choiceHttpMethod(type), requestEntity, String.class);
                resultObj = responseEntity.getBody();
            }
            return resultObj;
        } catch (Exception e) {
            JSONObject errorObj = new JSONObject();
            errorObj.put("url", url);
            errorObj.put("type", type);
            Result result = new Result(ResultCodeEnum.C505, errorObj);
            return JSONObject.fromObject(result).toString();
        }
    }

    /**
     * 服务调用,返回响应体,可获取所有响应信息,如响应头,响应code等
     *
     * @param url
     * @param type
     * @param paramType
     * @param headerMap
     * @param paramMap
     * @return
     */
    public ResponseEntity<String> invServiceForResultEntity(String url, String type, String paramType, Map<String, String> headerMap, Map<String, String> paramMap) {
        try {
            ResponseEntity<String> responseEntity = null;
            HttpEntity requestEntity = buildRequestEntity(paramType, headerMap, paramMap);
            responseEntity = restTemplate.exchange(url, choiceHttpMethod(type), requestEntity, String.class);
            return responseEntity;
        } catch (Exception e) {
            e.printStackTrace();
            JSONObject errorObj = new JSONObject();
            errorObj.put("url", url);
            errorObj.put("type", type);
            throw new BizException(BizExceptionCodeEnum.INVOKING_ERROR, errorObj.toString());
        }
    }

    /**
     * 构建http请求配置
     *
     * @param paramType
     * @param headerMap
     * @param paramMap
     * @return
     */
    public HttpEntity buildRequestEntity(String paramType, Map<String, String> headerMap, Map<String, String> paramMap) {
        HttpEntity requestEntity = null;
        HttpHeaders headers = setHeaders(headerMap);
        if ("BODY".equalsIgnoreCase(paramType)) {
            headers.setContentType(MediaType.valueOf("application/json;UTF-8"));
            String param = "";
            if (null != paramMap) {
                for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                    param = entry.getValue();
                    break;
                }
            }
            requestEntity = new HttpEntity(JSONObject.fromObject(param), headers);
        } else {
            MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
            if (null != paramMap) {
                for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                    params.add(entry.getKey(), entry.getValue());
                }
            }
            requestEntity = new HttpEntity(params, headers);
        }
        return requestEntity;
    }

    /**
     * 设置请求头部信息
     *
     * @param headerMap
     * @return
     */
    public HttpHeaders setHeaders(Map<String, String> headerMap) {
        HttpHeaders headers = new HttpHeaders();
        if (null == headerMap) {
            return headers;
        }
        for (Map.Entry<String, String> entry : headerMap.entrySet()) {
            headers.set(entry.getKey(), entry.getValue());
        }
        return headers;
    }

    /**
     * 选择请求方式
     *
     * @param type
     * @return
     */
    public HttpMethod choiceHttpMethod(String type) {
        if ("GET".equalsIgnoreCase(type)) {
            return HttpMethod.GET;
        } else if ("POST".equalsIgnoreCase(type)) {
            return HttpMethod.POST;
        } else if ("PUT".equalsIgnoreCase(type)) {
            return HttpMethod.PUT;
        } else if ("DELETE".equalsIgnoreCase(type)) {
            return HttpMethod.DELETE;
        } else if ("HEAD".equalsIgnoreCase(type)) {
            return HttpMethod.HEAD;
        } else if ("PATCH".equalsIgnoreCase(type)) {
            return HttpMethod.PATCH;
        } else if ("OPTIONS".equalsIgnoreCase(type)) {
            return HttpMethod.OPTIONS;
        } else if ("TRACE".equalsIgnoreCase(type)) {
            return HttpMethod.TRACE;
        } else {
            return HttpMethod.POST;
        }
    }

}

 

### 回答1: 可以使用Spring BootRestTemplate下载文件,方法如下: 1. 创建一个RestTemplate实例: ``` @Autowired private RestTemplate restTemplate; ``` 2. 使用exchange方法发送HTTP请求,将响应内容写入文件: ``` ResponseEntity<byte[]> response = restTemplate.exchange(url, HttpMethod.GET, null, byte[].class); byte[] file = response.getBody(); try (FileOutputStream fos = new FileOutputStream("path/to/file")) { fos.write(file); } ``` 注意: 在使用exchange方法时,需要指定HTTP方法(如GET, POST等)以及响应内容的类型(byte[]类型). 希望这些信息能帮到你! ### 回答2: 使用Spring BootRestTemplate下载文件可以通过以下步骤实现: 1. 首先,需要在Spring Boot的配置文件中配置一个RestTemplate的Bean,例如: ```java @Bean public RestTemplate restTemplate() { return new RestTemplate(); } ``` 2. 然后,使用RestTemplate的`getForObject`方法发送GET请求,将文件内容以字节数组的形式返回,例如: ```java RestTemplate restTemplate = new RestTemplate(); byte[] fileBytes = restTemplate.getForObject(fileUrl, byte[].class); ``` 其中,`fileUrl`是文件的URL地址。 3. 最后,将字节数组保存为文件,可以使用FileUtils类或者IO流的方式,例如: 使用FileUtils类: ```java FileUtils.writeByteArrayToFile(new File(filePath), fileBytes); ``` 其中,`filePath`是保存文件的路径。 使用IO流: ```java try (FileOutputStream fileOutputStream = new FileOutputStream(filePath)) { fileOutputStream.write(fileBytes); } ``` 以上就是使用Spring BootRestTemplate下载文件的简单步骤。需要注意的是,这种方式适用于小文件的下载,如果文件较大,可能会导致内存溢出,可以考虑使用`getForEntity`方法获取ResponseEntity,然后利用ResponseEntity的`getBody`方法获取输入流,并使用IO流逐行写入文件的方式进行下载,以避免内存溢出的问题。 ### 回答3: 使用Spring BootRestTemplate下载文件可以通过以下步骤实现: 1. 创建RestTemplate对象: ```java RestTemplate restTemplate = new RestTemplate(); ``` 2. 设置文件下载的请求头: ```java HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM)); HttpEntity<String> entity = new HttpEntity<>(headers); ``` 3. 发送HTTP GET请求并获取响应: ```java ResponseEntity<byte[]> response = restTemplate.exchange(url, HttpMethod.GET, entity, byte[].class); ``` 4. 检查响应状态码: ```java if (response.getStatusCode() == HttpStatus.OK) { byte[] file = response.getBody(); // 将文件保存到本地 Files.write(Paths.get("文件路径"), file); } else { // 处理请求失败的情况 } ``` 这样就可以使用RestTemplate下载文件。其中,`url`是文件的URL地址,可以是远程文件的地址或者是服务器上的文件路径。在执行下载文件的过程中,我们设置了请求头`Accept`为`application/octet-stream`,表示请求的响应应该是一个二进制文件。在获取到响应后,我们通过`ResponseEntity`的`getBody()`方法获取响应的数据,并将其保存到本地。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值