All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tech.mhuang.pacebox.springboot.autoconfiguration.datasecure.advice.DataSecureRequestBodyAdvice Maven / Gradle / Ivy

There is a newer version: 2023.0.0.0
Show newest version
package tech.mhuang.pacebox.springboot.autoconfiguration.datasecure.advice;

import com.alibaba.fastjson2.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter;
import tech.mhuang.pacebox.core.exception.BusinessException;
import tech.mhuang.pacebox.core.io.IOUtil;
import tech.mhuang.pacebox.core.util.ObjectUtil;
import tech.mhuang.pacebox.core.util.StringUtil;
import tech.mhuang.pacebox.springboot.autoconfiguration.datasecure.DataSecureInfo;
import tech.mhuang.pacebox.springboot.autoconfiguration.datasecure.DataSecureProperties;
import tech.mhuang.pacebox.springboot.autoconfiguration.datasecure.annation.DataSecureField;
import tech.mhuang.pacebox.springboot.autoconfiguration.datasecure.annation.DecryptMapping;
import tech.mhuang.pacebox.springboot.autoconfiguration.datasecure.consts.DecryptType;
import tech.mhuang.pacebox.springboot.core.spring.util.DataUtil;
import tech.mhuang.pacebox.springboot.protocol.Result;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Objects;


/**
 * 请求数据解密
 *
 * @author mhuang
 * @since 1.0.0
 */
@ControllerAdvice
public class DataSecureRequestBodyAdvice extends RequestBodyAdviceAdapter {

    private final DataSecureProperties secretProperties;

    public DataSecureRequestBodyAdvice(DataSecureProperties properties) {
        this.secretProperties = properties;
    }

    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class> aClass) {
        return Objects.requireNonNull(methodParameter.getMethod()).isAnnotationPresent(DecryptMapping.class) ||
                methodParameter.getContainingClass().isAnnotationPresent(DecryptMapping.class);
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class> aClass) throws IOException {
        DecryptMapping decryptMapping = Objects.requireNonNull(methodParameter.getMethod()).getAnnotation(DecryptMapping.class);
        if (ObjectUtil.isEmpty(decryptMapping)) {
            decryptMapping = methodParameter.getContainingClass().getAnnotation(DecryptMapping.class);
        }

        //获取配置项
        DataSecureInfo dataSecureInfo;
        String configKey = decryptMapping.value();
        if (StringUtil.isEmpty(configKey)) {
            dataSecureInfo = secretProperties;
        } else if (secretProperties.getDataSecurePropertiesMap().containsKey(configKey)) {
            dataSecureInfo = secretProperties.getDataSecurePropertiesMap().get(configKey);
        } else {
            throw new BusinessException(Result.SYS_FAILD, String.format("找不到配置项:%s", configKey));
        }

        //应答数据
        String httpBody;
        //整体解密
        if (decryptMapping.type() == DecryptType.ALL) {
            httpBody = decryptBody(httpInputMessage, dataSecureInfo);
        } else {
            //字段解密
            Field[] fields = methodParameter.getParameter().getType().getDeclaredFields();
            Object entity = JSON.parseObject(toString(httpInputMessage, dataSecureInfo), type);
            for (Field field : fields) {
                //需要处理的字段
                if (field.isAnnotationPresent(DataSecureField.class)) {
                    DataSecureField dataSecureField = field.getAnnotation(DataSecureField.class);
                    try {
                        Object proceeFieldValue = DataUtil.getValueByModelKey(entity, field.getName(), field.getType());
                        if (dataSecureField.decode() && ObjectUtil.isNotEmpty(proceeFieldValue)) {
                            DataUtil.setValueByModel(entity, field.getName(), dataSecureField.Clazz().getDeclaredConstructor().newInstance().decrypt(
                                    proceeFieldValue instanceof String ? (String) proceeFieldValue : JSON.toJSONString(proceeFieldValue),
                                    dataSecureInfo.getPrivateKey()
                            ));
                        }
                    } catch (Exception e) {
                        throw new BusinessException(Result.SYS_FAILD, "处理字段异常", e);
                    }
                }
            }
            httpBody = JSON.toJSONString(entity);
        }
        return new DataSecureHttpMessage(new ByteArrayInputStream(httpBody.getBytes()), httpInputMessage.getHeaders());
    }

    private String decryptBody(HttpInputMessage httpInputMessage, DataSecureInfo dataSecureInfo) throws IOException {
        String encryptBody = toString(httpInputMessage, dataSecureInfo);
        try {
            return dataSecureInfo.getEncryptDataInterface().getDeclaredConstructor().newInstance().decrypt(encryptBody, dataSecureInfo.getPrivateKey());
        } catch (Exception e) {
            throw new BusinessException(Result.SYS_FAILD, "数据解密异常", e);
        }
    }

    private String toString(HttpInputMessage httpInputMessage, DataSecureInfo dataSecureInfo) throws IOException {
        InputStream encryptStream = httpInputMessage.getBody();
        try {
            return IOUtil.toString(encryptStream, dataSecureInfo.getEncryptDataInterface().getDeclaredConstructor().newInstance().getDecryptCoding().toString());
        } catch (Exception e) {
            throw new BusinessException(Result.SYS_FAILD, "数据解密异常", e);
        }
    }

    @Data
    @AllArgsConstructor
    static
    class DataSecureHttpMessage implements HttpInputMessage {
        private InputStream body;
        private HttpHeaders httpHeaders;

        @Override
        public InputStream getBody() {
            return this.body;
        }

        @Override
        public HttpHeaders getHeaders() {
            return this.httpHeaders;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy