自定义解密注解

2023-11-05

在开发中,有时候会遇到前端body加密,后端解密操作,接下来用注解实现

1、新增DecodeRequestBodyAdvice类

package com.xx.advice;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
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.RequestBodyAdvice;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;

@ControllerAdvice(basePackages = "com.xx.controller")
@Slf4j
public class DecodeRequestBodyAdvice implements RequestBodyAdvice {
    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return body;
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
        try {
            boolean encode = false;
            if (methodParameter.getMethod().isAnnotationPresent(AesDecrypt.class)) {
                //获取注解配置的包含和去除字段
                AesDecrypt serializedField = methodParameter.getMethodAnnotation(AesDecrypt.class);
                //入参是否需要解密
                encode = serializedField.inDecode();
            }
            if (encode) {
                log.info("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行解密");
                return new MyHttpInputMessage(inputMessage);
            } else {
                return inputMessage;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行解密出现异常:" + e.getMessage());
            return inputMessage;
        }
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return body;
    }


    class MyHttpInputMessage implements HttpInputMessage {
        private HttpHeaders headers;
        private InputStream body;

        public MyHttpInputMessage(HttpInputMessage httpInputMessage) throws Exception {
            this.headers = httpInputMessage.getHeaders();
            String requestData = IOUtils.toString(httpInputMessage.getBody(), "utf-8");
            System.out.println("--encryptStr:" + requestData);
            String encryptStr = easpString(requestData).replace("\"", "");
            String decrypt = AESUtil.decrypt(encryptStr);
            this.body = IOUtils.toInputStream(decrypt, "utf-8");
        }

        @Override
        public InputStream getBody() throws IOException {
            return body;
        }

        @Override
        public HttpHeaders getHeaders() {
            return headers;
        }

        public String easpString(String requestData) {
            if (requestData != null && !requestData.equals("")) {
                String s = "{\"encryptStr\":";
                //去除requestData中的转义字符
                String data = requestData.replaceAll("\\s*|\r|\n|\t", "");
                if (!data.startsWith(s)) {
                    throw new RuntimeException("参数【encryptStr】缺失异常!");
                } else {
                    int closeLen = data.length() - 1;
                    int openLen = "{\"encryptStr\":".length();
                    String substring = StringUtils.substring(data, openLen, closeLen);
                    return substring;
                }
            }
            return "";
        }

    }
}

2、新增AesDecrypt

package com.xx.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface AesDecrypt {

    //入参是否解密,默认解密
    boolean inDecode() default true;
    //出参是否加密,默认加密
    boolean outEncode() default true;

}

注意:AESUtil可以直接网上copy一份,和前端一一对应加密秘钥

3、使用

@PostMapping("/addUser")
    @AesDecrypt
    public ResponseBean<String> addUser(@RequestBody UserLoginRequest loginRequest) {
        ResponseBean<String> responseBean = new ResponseBean<>();
        sysUserService.addUser(loginRequest);
        responseBean.setSuccess(true);
        responseBean.setMessage("新增用户成功");
        return responseBean;
  }

即可解密

4、前端请求body

{"encryptStr":"加密body"}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自定义解密注解 的相关文章

随机推荐