介绍说明
在该场景下一般使用于系统和其他平台通过restful api的对接 ,一般的处理思路是使用http请求工具和服务端交互 , 目前我们系统中常用的工具有 httpClient和restTemplate (Spring系列中对于httpClient的封装) , 通常是在访问配置中设置SSL的具体内容
源码实例
示例取自xxx收集器collector中com.ants.collector.util.httpTools.RestTemplateUtils
.java;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import javax.net.ssl.SSLContext;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
@Slf4j
public class RestTemplateUtils
{
static final int connectTimeOut = 1000 * 10;
public static 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);
//默认允许所有的域名 , 如果不指定域名的话某些域名无法访问
SSLConnectionSocketFactory
csf = new SSLConnectionSocketFactory(sslContext,
SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
CloseableHttpClient httpClient
= HttpClients.custom()
.setSSLSocketFactory(csf)
.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
requestFactory.setConnectTimeout(connectTimeOut);
RestTemplate restTemplate = new RestTemplate(requestFactory);
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}
/**
* 执行调用restful接口
*
* @param url 资源地址
* @param methodType
调用方法类型HttpMethod.GET...
* @param httpBody httpBody类型
* @param returnType
返回类型
* @param <T>
* @param <R>
* @return
*/
public static <T, R> R restfulInvoke(String url, HttpMethod methodType,
HttpHeaders headers, T httpBody, Class<R>
returnType) {
HttpEntity entity = new HttpEntity(httpBody, headers);
ResponseEntity<R>
exchange = null;
try {
exchange = RestTemplateUtils.restTemplate().exchange(url,
methodType, entity, returnType);
return exchange.getBody();
} catch (KeyStoreException | NoSuchAlgorithmException |
KeyManagementException e) {
log.info("https验证异常", e);
}
return null;
}
public static void main(String[] args) throws NoSuchAlgorithmException,
KeyStoreException, KeyManagementException {
String url = "http://180.166.132.100/mock/128/data/entryDeclportSta/cen043/v1";
RestTemplate restTemplate = restTemplate();
JSONObject body = JSONObject.parseObject("{ \n" +
" \"auth\": { \n" +
" \"identity\": { \n" +
" \"methods\": [\"password\"], \n" +
" \"password\": { \n" +
" \"user\": { \n" +
" \"name\": \"qy_admin\", \n" +
" \"password\": \"Huawei@123\", \n" +
" \"domain\": { \n" +
"
\"name\": \"qy_tenant\" \n" +
" }
\n" +
" } \n" +
" } \n" +
" }, \n" +
" \"scope\": { \n" +
" \"project\": { \n" +
" \"id\": \"5f4d3cf5d4824b98b4164c7c58f0076a\" \n" +
" } \n" +
" } \n" +
" } \n" +
"}");
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
HttpEntity entity = new HttpEntity(body, headers);
ResponseEntity<JSONObject> response = restTemplate.exchange(url,
HttpMethod.POST, null,
JSONObject.class);
System.out.println(response.toString());
}
}
|
Spring应用中启用HTTPS
介绍说明
在该场景下一般使用于springboot单体应用发布服务用户通过http或者https访问 ,一般的处理思路是先在应用中配置SSL ,是应用可以接收HTTPS的请求 , 同时提供http的入口 ,将http的请求在程序内容转达给https进行处理
具体步骤:
- 生成ssl证书
- 将证书导入项目 , 配置启用ssl
- 将http端口的请求转发到https
- 使用jdk工具生成ssl证书
源码实例
#在jdk环境下直接输入此命令 生成tomcat使用的证书 路径和名称和密码参数可以重新指定
keytool -genkey -alias qunyi -keypass changingit!@# -keyalg RSA
-keysize 1024 -validity 999 -keystore D:/keys/qunyi.keystore -storepass
changingit!@#
#示例参数 视情况而定 也可以不设置 直接enter
您的名字与姓氏是什么?
[Unknown]:
www.changingit.cn
您的组织单位名称是什么?
[Unknown]:
xxx
您的组织名称是什么?
[Unknown]:
xxxx
您所在的城市或区域名称是什么?
[Unknown]:
shanghai
您所在的省/市/自治区名称是什么?
[Unknown]:
shanghai
该单位的双字母国家/地区代码是什么?
[Unknown]:
zh
CN=www.changingit.cn,
OU=qunyi, O=qunyi, L=shanghai, ST=shanghai, C=zh是否正确?
[否]: y
|
- 将生成的证书导入项目 , 添加ssl的相关配置
并且重新配置应用的端口号
注意这里的端口配置 , 修改以后程序的主端口(https端口)一般和原本的端口(http端口)是不一致的 , 有可能会引起和端口相关的程序逻辑处理
3.支持监听http和https配置
将http端口获取到的请求信息 内部转发到https进行处理 , 系统中添加配置项
import org.apache.catalina.connector.Connector;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
@Configuration
public class HttpsConnectorConfig {
@Value("${http.port}")
private Integer port;
@Bean
public ServletWebServerFactory
servletContainer() {
TomcatServletWebServerFactory
tomcat = new TomcatServletWebServerFactory();
// 添加http
tomcat.addAdditionalTomcatConnectors(createStandardConnector());
return tomcat;
}
/**
* 配置http
* @return
*/
private Connector
createStandardConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(port);
return connector;
}
}
|
注意这里某些配置方式 可能会导致请求head和body中的部分参数丢失 , 该实例中无此问题