系统中接入HTTPS类型的应用

介绍说明

在该场景下一般使用于系统和其他平台通过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进行处理

具体步骤:

  1. 生成ssl证书
  2. 将证书导入项目 , 配置启用ssl
  3. 将http端口的请求转发到https
  4. 使用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

 

 

  1. 将生成的证书导入项目 , 添加ssl的相关配置 并且重新配置应用的端口号系统中接入HTTPS类型的应用

     

系统中接入HTTPS类型的应用

 

 


注意这里的端口配置 , 修改以后程序的主端口(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中的部分参数丢失 , 该实例中无此问题

 

系统中接入HTTPS类型的应用

上一篇:css的四种引入方式


下一篇:使用json-lib进行Java和JSON之间的转换