@ControllerAdvice 结合 RequestBodyAdviceAdapter 和 ResponseBodyAdvice 实现对请求的加密解密

5 篇文章 0 订阅

@ControllerAdvice 结合 RequestBodyAdviceAdapter 和 ResponseBodyAdvice 实现对请求的加密解密

  • @ControllerAdvice 是对controller 的增强。 结合 RequestBodyAdviceAdapter 和 ResponseBodyAdvice 实现对请求的加密解密, 可以实现类似filter 的功能, 对请求进行前置处理和后置处理。

  • 应用场景

    • 加密解密
  • 示例

    • 请求controller

      • import org.springframework.web.bind.annotation.PostMapping;
        import org.springframework.web.bind.annotation.RequestBody;
        import org.springframework.web.bind.annotation.RequestHeader;
        import org.springframework.web.bind.annotation.RequestMapping;
        
        
        @RequestMapping("/test")
        public interface TestActionService {
        
         
            @PostMapping(value = "/testExchange")
            @RequestDecode(method = EncryptEnum.AES)
            @ResponseEncode(method = EncryptEnum.AES)
            TestVO testExchange(@RequestBody TestVO request, @RequestHeader(value = "channelCode") String channelCode);
        }
        
    • 加密 beforeBodyRead前置处理

      • 
        import lombok.extern.slf4j.Slf4j;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.core.MethodParameter;
        import org.springframework.http.HttpHeaders;
        import org.springframework.http.HttpInputMessage;
        import org.springframework.http.converter.HttpMessageConverter;
        import org.springframework.stereotype.Component;
        import org.springframework.util.StringUtils;
        import org.springframework.web.bind.annotation.ControllerAdvice;
        import org.springframework.web.bind.annotation.RequestBody;
        import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter;
        
        import javax.annotation.Resource;
        import java.io.ByteArrayInputStream;
        import java.io.ByteArrayOutputStream;
        import java.io.IOException;
        import java.io.InputStream;
        import java.lang.reflect.Type;
        import java.nio.charset.Charset;
        import java.nio.charset.StandardCharsets;
        
        /**
         * 解密请求参数
         *
         */
        @Slf4j
        @Configuration
        // assignableTypes 指定对那个controller 类增强
        @ControllerAdvice(assignableTypes = {TestActionService.class})
        public class DecodeRequestBodyAdvice extends RequestBodyAdviceAdapter {
        
            @Resource
            private EncryptConfig encryptConfig;
            /**
             * 判断是否支持解密
             * @param methodParameter
             * @param targetType
             * @param converterType
             * @return
             */
            @Override
            public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
                return methodParameter.getMethodAnnotation(RequestDecode.class) != null
                        && methodParameter.getParameterAnnotation(RequestBody.class) != null;
        
            }
        
            /**
             * 在参数请求处理解密
             * @param request
             * @param parameter
             * @param targetType
             * @param converterType
             * @return
             * @throws IOException
             */
            @Override
            public HttpInputMessage beforeBodyRead(HttpInputMessage request, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        
                RequestDecode requestDecode = parameter.getMethodAnnotation(RequestDecode.class);
                if (requestDecode == null) {
                    return request;//controller方法不要求加解密
                }
                EncryptEnum method = requestDecode.method();
                //这里灵活的可以支持到多种加解密方式
                switch (method) {
                    case NULL:
                        break;
                    case AES: {
                        InputStream is = request.getBody();
                        /*ByteBuf buf = PooledByteBufAllocator.DEFAULT.heapBuffer();
                        int ret = -1;
                        int len = 0;
                        while((ret = is.read()) > 0) {
                            buf.writeByte(ret);
                            len ++;
                        }
                        String body = buf.toString(0, len, Charset.defaultCharset());
                        buf.release();*/
        
        
                        ByteArrayOutputStream result = new ByteArrayOutputStream();
                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = is.read(buffer)) != -1) {
                            result.write(buffer, 0, length);
                        }
                        String body = result.toString(StandardCharsets.UTF_8.name());
        
                        String temp = null;
                        try {
                            //解密处理
                            String key = encryptConfig.getKeyMaps().get(comCode);
                            temp =  AesEncryptUtils.decrypt(body,key);
                            log.info("解密完成: {}", temp);
                            return new DecodedHttpInputMessage(request.getHeaders(), new ByteArrayInputStream(temp.getBytes("UTF-8")));
                        } catch (Exception e) {
                            log.error("解密失败 {} 待解密密文: {}",comCode,  body, e);
                            throw new RequestException("-1","解密失败!");
                        }
        
                    }
                }
                return request;
            }
        
            static class DecodedHttpInputMessage implements HttpInputMessage {
                HttpHeaders headers;
                InputStream body;
        
                public DecodedHttpInputMessage(HttpHeaders headers, InputStream body) {
                    this.headers = headers;
                    this.body = body;
                }
        
                @Override
                public InputStream getBody() throws IOException {
                    return body;
                }
        
                @Override
                public HttpHeaders getHeaders() {
                    return headers;
                }
            }
        
        
        }
        
        
    • 解密

      • import com.alibaba.fastjson.JSON;
        import lombok.extern.slf4j.Slf4j;
        import org.springframework.core.MethodParameter;
        import org.springframework.http.MediaType;
        import org.springframework.http.server.ServerHttpRequest;
        import org.springframework.http.server.ServerHttpResponse;
        import org.springframework.stereotype.Component;
        import org.springframework.web.bind.annotation.ControllerAdvice;
        import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
        
        import javax.annotation.Resource;
        
        
        /**
         * 响应请求加密
         *
         */
        @Slf4j
        @Component
        @ControllerAdvice(assignableTypes = {TestActionService.class})
        public class EncodeResponseBodyAdvic implements ResponseBodyAdvice {
        
            @Resource
            private EncryptConfig encryptConfig;
        
            @Override
            public boolean supports(MethodParameter returnType, Class converterType) {
                return returnType.getMethodAnnotation(ResponseEncode.class) != null;
            }
        
            @Override
            public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        
                ResponseEncode responseEncode = returnType.getMethodAnnotation(ResponseEncode.class);
                EncryptEnum method = responseEncode.method();
        
                switch (method) {
                    case NULL:
                        break;
                    case AES: {
                        String temp = JSON.toJSONString(body);
                        log.info("待加密数据: {}", temp);
                        try{
                            String channelCode = request.getHeaders().getFirst("channelCode");
                            String key =encryptConfig.getKeyMaps().get(channelCode);
                            String encryptBody = AesEncryptUtils.encrypt(temp, key);
                            log.debug("加密完成: {}", encryptBody);
                            response.getHeaders().set("Content-Type", "application/json;charset=UTF-8");
                            return encryptBody;
                        }catch (Exception e){
                            log.error("加密异常:",e);
                            throw  new RequestException("-1","加密异常!");
                        }
                    }
                }
                return body;
            }
        
        
        }
        
        
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BinBin_Bang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值