有这样一个需求,拿到一份其他园区的五位一体数据对接文档,要求根据文档实现类似的服务端提供企业传输数据‘

image-20230512100249705

实现方式(下文采用的是HttpMessageConverter的方式,还有其他方式暂不列举)

消息转换器

package com.lyc.wwyt.config.convert;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lyc.wwyt.exception.DecryptException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.StreamUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.Map;

public class DecryptingHttpMessageConverter extends MappingJackson2HttpMessageConverter {
    private static final String KEY = "xxxxxxxxxxxxxxxxx";
    private static final String INITIALIZATION_VECTOR = "xxxxxxxxxxxxxxxxx";

    private final ObjectMapper objectMapper;

    public DecryptingHttpMessageConverter(ObjectMapper objectMapper) {
        super(objectMapper);
        this.objectMapper = objectMapper;
        setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
    }

    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return true;
    }

    @Override
    public Object read(Type type, Class<?> clazz, HttpInputMessage inputMessage) throws IOException {
        JavaType javaType = this.getJavaType(type, clazz);
        String body = StreamUtils.copyToString(inputMessage.getBody(), StandardCharsets.UTF_8);
        Map<String, Object> map = objectMapper.readValue(body, new TypeReference<Map<String, Object>>() {
        });
        String encryptedDatas = (String) map.get("datas");
        String decryptedDatas = decrypt(encryptedDatas);
        String decryptedBody;
        if (List.class.isAssignableFrom(javaType.getRawClass())) {
            List<Map<String, Object>> decryptedList = objectMapper.readValue(decryptedDatas, new TypeReference<List<Map<String, Object>>>() {
            });
            decryptedBody = objectMapper.writeValueAsString(decryptedList);
        } else {
            Map<String, Object> decryptedMap = objectMapper.readValue(decryptedDatas, new TypeReference<Map<String, Object>>() {
            });
            map.putAll(decryptedMap);
            map.remove("datas");
            decryptedBody = objectMapper.writeValueAsString(map);
        }

        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decryptedBody.getBytes());
        HttpHeaders headers = inputMessage.getHeaders();
        return this.objectMapper.readValue(byteArrayInputStream, javaType);
    }

    private String decrypt(String encrypted) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec key = new SecretKeySpec(KEY.getBytes(StandardCharsets.UTF_8), "AES");
            IvParameterSpec iv = new IvParameterSpec(INITIALIZATION_VECTOR.getBytes(StandardCharsets.UTF_8));
            cipher.init(Cipher.DECRYPT_MODE, key, iv);
            byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encrypted));
            return new String(decrypted, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new DecryptException();
        }
    }
}

将其添加到消息转换器中

package com.lyc.wwyt.config.convert;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

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

/**
 * 类 WebMvcConfig
 *
 * @author ChenQi
 * @date 2023/5/11
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Resource
    private ObjectMapper objectMapper;

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(0, new DecryptingHttpMessageConverter(objectMapper));
    }
}

实现效果

image-20230512111359520

代码地址

源码