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 - 博客园


相关文章
|
1月前
|
分布式计算 关系型数据库 MySQL
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型 图像处理 光通信 分布式计算 算法语言 信息技术 计算机应用
55 8
|
1月前
|
存储 JSON 安全
商品详情(item getAPI接口)json数据格式参考
某东商品详情(item get API接口)的JSON数据格式参考如下
|
1月前
|
JSON Java 数据格式
springboot中表字段映射中设置JSON格式字段映射
springboot中表字段映射中设置JSON格式字段映射
125 1
|
1月前
|
JSON API 数据格式
商品详情(item getAPI接口)json数据格式参考
淘宝商品详情(item get API接口)返回的JSON数据格式是一个复杂且灵活的结构,包含多个字段和对象。以下是一个简化的JSON数据格式参考:
|
1月前
|
JSON API 数据格式
店铺所有商品列表接口json数据格式示例(API接口)
当然,以下是一个示例的JSON数据格式,用于表示一个店铺所有商品列表的API接口响应
|
1月前
|
JSON API 数据安全/隐私保护
拍立淘按图搜索API接口返回数据的JSON格式示例
拍立淘按图搜索API接口允许用户通过上传图片来搜索相似的商品,该接口返回的通常是一个JSON格式的响应,其中包含了与上传图片相似的商品信息。以下是一个基于淘宝平台的拍立淘按图搜索API接口返回数据的JSON格式示例,同时提供对其关键字段的解释
|
2月前
|
JSON JavaScript API
(API接口系列)商品详情数据封装接口json数据格式分析
在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦!
|
1月前
|
关系型数据库 MySQL Java
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
34 0
|
3月前
|
JSON 前端开发 JavaScript
java中post请求调用下载文件接口浏览器未弹窗而是返回一堆json,为啥
客户端调接口需要返回另存为弹窗,下载文件,但是遇到的问题是接口调用成功且不报错,浏览器F12查看居然返回一堆json,而没有另存为弹窗; > 正确的效果应该是:接口调用成功且浏览器F12不返回任何json,而是弹窗另存为窗口,直接保存文件即可。
158 2
|
3月前
|
JSON API 数据格式
requests库中json参数与data参数使用方法的深入解析
选择 `data`或 `json`取决于你的具体需求,以及服务器端期望接收的数据格式。
290 2
下一篇
DataWorks