springboot使用自定义注解实现接口参数解密,普通字段,json,集合

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: springboot版本 2.4.9

springboot版本 2.4.9


话不多说,直接上代码


代码中的json工具和加密工具均是使用的hutool包中的


依赖


<dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.11</version>
        </dependency>

先来自定义一个注解


@Target({ElementType.METHOD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamsAESAnno {
}

使用@Target注解标明此注解能用在方法和参数上面


使用@Retention注解标明此注解作用在运行阶段


然后我们要处理接口参数的话,需要自定义参数解析器,实现springMvc的

HandlerMethodArgumentResolver
@Log4j2
public class AESDecodeResolver implements HandlerMethodArgumentResolver {
    /*
         秘钥
     */
    public static final String KEY = "vhukzevhukze1234";
    /*
        json参数的key
     */
    private static final String NAME = "str";
    /**
     * 如果接口或者接口参数有解密注解,就解析
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasMethodAnnotation((ParamsAESAnno.class)) || parameter.hasParameterAnnotation(ParamsAESAnno.class);
    }
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer modelAndViewContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        //AES
        AES aes = SecureUtil.aes(KEY.getBytes(StandardCharsets.UTF_8));
        //如果是实体类参数,把请求参数封装
        if (BaseReq.class.isAssignableFrom(parameter.getParameterType())) {
            //获取加密的请求数据并解密
            String beforeParam = webRequest.getParameter(NAME);
            String afterParam = aes.decryptStr(beforeParam, CharsetUtil.CHARSET_UTF_8);
            //json转对象  // 这里的return就会把转化过的参数赋给控制器的方法参数
            return JSONUtil.toBean(afterParam, parameter.getParameterType());
            // 如果是非集合类,就直接解码返回
        } else if (!Iterable.class.isAssignableFrom(parameter.getParameterType())) {
            String decryptStr = aes.decryptStr(webRequest.getParameter(parameter.getParameterName()), CharsetUtil.CHARSET_UTF_8);
            return Integer.class.isAssignableFrom(parameter.getParameterType()) ? Integer.parseInt(decryptStr) : decryptStr;
            //如果是集合类
        } else {
            //获取加密的请求数据并解密
            String beforeParam = webRequest.getParameter(NAME);
            String afterParam = aes.decryptStr(beforeParam, CharsetUtil.CHARSET_UTF_8);
            //转成对象数组
            JSONArray jsonArray = JSONUtil.parseArray(afterParam);
            return jsonArray.stream()
                    .map(json -> JSONUtil.toBean(json.toString(), parameter.getParameterType()))
                    .collect(Collectors.toList());
        }
    }
}


但是现在post请求都是用json提交,不用表单提交了,如果是json提交的话,改成下面这样


import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.gt.SPYZT.annotation.ParamsAESAnno;
import com.gt.SPYZT.entity.dto.BaseReq;
import com.gt.SPYZT.utils.AESUtil;
import lombok.extern.log4j.Log4j2;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;
import java.util.stream.Collectors;
/**
 * 解析加密注解
 *
 * @author vhukze
 * @date 2021/9/8 11:14
 */
@Log4j2
public class AESDecodeResolver implements HandlerMethodArgumentResolver {
    /*
        json参数的key
     */
    private static final String NAME = "str";
    /**
     * 如果接口或者接口参数有解密注解,就解析
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasMethodAnnotation((ParamsAESAnno.class)) || parameter.hasParameterAnnotation(ParamsAESAnno.class);
    }
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer modelAndViewContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory webDataBinderFactory) throws IOException {
        //aes
        AES aes = AESUtil.aes;
        //获取post请求的json数据
        HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
        int contentLength = request.getContentLength();
        if (contentLength < 0) {
            return null;
        }
        byte[] buffer = new byte[contentLength];
        for (int i = 0; i < contentLength; ) {
            int readlen = request.getInputStream().read(buffer, i,
                    contentLength - i);
            if (readlen == -1) {
                break;
            }
            i += readlen;
        }
        String str = new String(buffer,CharsetUtil.CHARSET_UTF_8);
        StringBuilder sb = new StringBuilder();
        for (char c : str.toCharArray()) {
            //去掉json中的空格 换行符 制表符
            if(c != 32 && c != 13 && c != 10){
                sb.append(c);
            }
        }
        //如果是实体类参数,把请求参数封装
        if (BaseReq.class.isAssignableFrom(parameter.getParameterType())) {
            //获取加密的请求数据并解密
//            String beforeParam = webRequest.getParameter(NAME);
            String afterParam = aes.decryptStr(JSONUtil.parseObj(sb.toString()).get(NAME).toString(), CharsetUtil.CHARSET_UTF_8);
            //json转对象  // 这里的return就会把转化过的参数赋给控制器的方法参数
            return JSONUtil.toBean(afterParam, parameter.getParameterType());
            // 如果是非集合类,就直接解码返回
        } else if (!Iterable.class.isAssignableFrom(parameter.getParameterType())) {
            String decryptStr = aes.decryptStr(webRequest.getParameter(parameter.getParameterName()), CharsetUtil.CHARSET_UTF_8);
            return Integer.class.isAssignableFrom(parameter.getParameterType()) ? Integer.parseInt(decryptStr) : decryptStr;
            //如果是集合类
        } else if(Iterable.class.isAssignableFrom(parameter.getParameterType())){
            //获取加密的请求数据并解密
//            String beforeParam = webRequest.getParameter(NAME);
            String afterParam = aes.decryptStr(sb.toString(), CharsetUtil.CHARSET_UTF_8);
            //转成对象数组
            JSONArray jsonArray = JSONUtil.parseArray(afterParam);
            return jsonArray.stream()
                    .map(json -> JSONUtil.toBean(JSONUtil.parseObj(sb.toString()).get(NAME).toString(), parameter.getParameterType()))
                    .collect(Collectors.toList());
        }
        return null;
    }
}


注册自定义解析器


@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
    //region 注册自定义HandlerMethodArgumentResolver
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(aesDecodeResolver());
    }
    @Bean
    public AESDecodeResolver aesDecodeResolver() {
        return new AESDecodeResolver();
    }
    //endregion
}

接下来就可以直接使用注解了


@RestController
@RequestMapping("test")
public class TestController {
    @ParamsAESAnno
    @GetMapping
    public RestfulResp<?> test(String str,Integer type) {
        return new RestfulResp<>().success();
    }
    @ParamsAESAnno
    @PostMapping("json")
    public RestfulResp<?> jsonTest(BaseReq baseReq){
        return new RestfulResp<>().success();
    }
    @ParamsAESAnno
    @PostMapping("jsonList")
    public RestfulResp<?> jsonTest(List<BaseReq> list){
        return new RestfulResp<>().success();
    }
}


效果图就不贴了,测试没有问题


如果想使用Validation包里面注解校验参数,请看我的另一篇博文:


使用反射实现@RequestBody的参数校验功能


本文参考博文:SpringBoot使用自定义注解实现简单参数加密解密(注解+HandlerMethodArgumentResolver) - yellowgg - 博客园


相关文章
|
11天前
|
JSON Java 数据格式
springboot中表字段映射中设置JSON格式字段映射
springboot中表字段映射中设置JSON格式字段映射
25 1
|
9天前
|
分布式计算 关系型数据库 MySQL
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型 图像处理 光通信 分布式计算 算法语言 信息技术 计算机应用
30 8
|
1月前
|
JSON API 数据格式
postman如何发送json请求其中file字段是一个图片
postman如何发送json请求其中file字段是一个图片
117 4
|
18天前
|
关系型数据库 MySQL Java
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
22 0
|
2月前
|
JSON API 数据格式
requests库中json参数与data参数使用方法的深入解析
选择 `data`或 `json`取决于你的具体需求,以及服务器端期望接收的数据格式。
216 2
|
2月前
|
JSON 数据库 数据格式
数据库表如果有json字段,该怎么更新
数据库表如果有json字段,该怎么更新
|
3月前
|
JSON C语言 数据格式
Python导出隐马尔科夫模型参数到JSON文件C语言读取
Python导出隐马尔科夫模型参数到JSON文件C语言读取
26 1
|
3月前
|
XML JSON Java
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
本文介绍了如何使用IntelliJ IDEA和Maven搭建一个整合了Struts2、Spring4、Hibernate4的J2EE项目,并配置了项目目录结构、web.xml、welcome.jsp以及多个JSP页面,用于刷新和学习传统的SSH框架。
88 0
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
|
3月前
|
JSON Java API
解码Spring Boot与JSON的完美融合:提升你的Web开发效率,实战技巧大公开!
【8月更文挑战第29天】Spring Boot作为Java开发的轻量级框架,通过`jackson`库提供了强大的JSON处理功能,简化了Web服务和数据交互的实现。本文通过代码示例介绍如何在Spring Boot中进行JSON序列化和反序列化操作,并展示了处理复杂JSON数据及创建RESTful API的方法,帮助开发者提高效率和应用性能。
147 0
|
3月前
|
JSON Java API
Jackson:SpringBoot中的JSON王者,优雅掌控数据之道
【8月更文挑战第29天】在Java的广阔生态中,SpringBoot以其“约定优于配置”的理念,极大地简化了企业级应用的开发流程。而在SpringBoot处理HTTP请求与响应的过程中,JSON数据的序列化和反序列化是不可或缺的一环。在众多JSON处理库中,Jackson凭借其高效、灵活和强大的特性,成为了SpringBoot中处理JSON数据的首选。今天,就让我们一起深入探讨Jackson如何在SpringBoot中优雅地控制JSON数据。
120 0