Spring体系下解决请求统一加解密之ResponseBodyAdvice和RequestBodyAdvice

在日常写项目中经常一般正规的项目都需要将信息加密后返回前端,前端进行解密后再展示出来给用户,这样做的目的无一不是为了安全,在Java开发中,如何简单快速的完成这个功能呢,这里就需要用到这两个接口ResponseBodyAdvice和RequestBodyAdvice。

ResponseBodyAdvice是 spring 4.1 新加入的一个接口,在消息体被HttpMessageConverter写入之前允许Controller 中 @ResponseBody修饰的方法调整响应中的内容,比如进行相应的加密或者进行统一处理返回值/响应体。【同样RequestBodyAdvice也是在 sping 新加入的一个接口,它可以使用在 @RequestBody 或 HttpEntity 修饰的参数读取之前进行参数的处理,比如进行参数的解密】 通俗来讲就是在数据返回前端之前可以通过这个ResponseBodyAdvice接口来将响应中的数据进行操作后再返回前端。接下来直接上代码

1.首先需要自己写一个类来实现ResponseBodyAdvice这个接口,然后重写方法

2.supports这个方法返回参数是布尔值,返回false则代表不走到beforeBodyWrite这个方法,返回true则代表走到这个方法。因此可以在这里进行检查方法是否有我们自己定义的注解,比如我的代码就是检查了方法参数上有没有EncryptBody这个注解,有的话就会去进行beforeBodyWrite方法的执行。

3.beforeBodyWrite这个方法中的参数body就是你返回前端的所有body,在这里可以判断参数类型,并对参数进行加密操作。

java 复制代码
@Component
@ControllerAdvice
public class EncryptBodyAdvice implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return returnType.hasMethodAnnotation(EncryptBody.class);
    }

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof AjaxResult) {
            //AjaxResult类型加密
            AjaxResult ajaxResult =(AjaxResult) body;
            ajaxResult.put("encrypt",true);

            Object bodyData = ajaxResult.get("data");
            ajaxResult.put("data",handleENCData(bodyData));
            return ajaxResult;
        } else if (body instanceof TableDataInfo) {
            //TableDataInfo类型加密
            TableDataInfo tableDataInfo =(TableDataInfo) body;
            tableDataInfo.setEncrypt(true);

            if (!CollectionUtils.isEmpty(tableDataInfo.getRows())){
                tableDataInfo.setRows(handleENCData(tableDataInfo.getRows()));
                return tableDataInfo;
            }

        }
        return body;
    }

    /**
     * 处理加密数据
     *
     * @param data 数据
     * @return {@link Object}
     */
    private Object handleENCData(Object data){
        if (Objects.isNull(data)){
            return data;
        }
        //自动关流
        try {

            return Base64.encode(objectMapper.writeValueAsString(data));
        }catch (Exception e){
            e.printStackTrace();
        }
        return data;
    }


    /**
     * 处理加密数据
     *
     * @param data 数据
     * @return {@link List}<{@link Object}>
     */
    private List<Object> handleENCData(List data){
        if (Objects.isNull(data)){
            return data;
        }
        try {
            List<Object> newData = new ArrayList<>();
            for (Object datum : data) {
                //base64加密
                newData.add(Base64.encode(objectMapper.writeValueAsString(datum)));
            }
            return newData;
        }catch (Exception e){
            e.printStackTrace();
        }
        return data;
    }

    //public static void main(String[] args) {
    //    try {
    //        String s="eyJjb2xsZWdlSWQiOiIzIiwic3RhZmZJZCI6IjEiLCJkZWxGbGFnIjoiMCIsInBpY3R1cmUiOiJodHRwczovL2NhYnMubXllYmtqLmNvbS9jYWJzaW1ncy9jYWJzLzIwMjQvMDEvMDkvMzMuanBnIiwibmFtZSI6IuiuuOW8uiIsIm51bWJlciI6IjEwMDAwIiwicGhvbmUiOiIiLCJzZXgiOiIwIiwiZGF0ZUJpcnRoIjoiMTk2OC0wNi0wMSIsImlkQ2FyZCI6IiIsInN0YWZmU3RhdHVzIjoiMCIsInRpdGxlIjoiMCIsImpvYiI6IjkiLCJjYXRlZ29yeSI6IjMiLCJ0ZWFjaGluZ0lkTmFtZSI6Ii0iLCJkZXB0TmFtZSI6IueOr+Wig+S4juWcn+acqOW3peeoi+WtpumZoiwg5Zyw6LSo5bel56iL57O7IiwidGVhY2hKb2JWYWx1ZSI6IuS4k+S4mui0n+i0o+S6uiIsImNhdGVnb3J5VmFsdWUiOiLlhbbku5YiLCJ0aXRsZVZhbHVlIjoi5pWZ5o6IIiwic3RhZmZTdGF0dXNWYWx1ZSI6IuWcqOiBjCIsInNleFZhbHVlIjoi55S3IiwiZWR1Y2F0aW9uIjoiMyJ9";
    //        System.out.println(new String(Base64.decode(s)));
    //        //System.out.println(Base64.encode("123456"));
    //    } catch (Exception e){
    //
    //    }
    //}
}

同理RequestBodyAdvice操作也类似,这里不再举例

java 复制代码
@Component
@ControllerAdvice
public class DecryptBodyAdvice implements RequestBodyAdvice {
    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return false;
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        return null;
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return null;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return null;
    }
}
相关推荐
源码姑娘5 分钟前
基于DeepSeek的智慧医药系统(源码+部署教程)
java·人工智能·程序人生·毕业设计·springboot·健康医疗·课程设计
morris13110 分钟前
【redis】布隆过滤器的Java实现
java·redis·布隆过滤器
uhakadotcom11 分钟前
FinGPT:金融领域的开源语言模型框架
后端·面试·github
五行星辰24 分钟前
Java链接redis
java·开发语言·redis
编程毕设24 分钟前
【含文档+PPT+源码】基于微信小程序的在线考试与选课教学辅助系统
java·微信小程序·小程序
异常驯兽师27 分钟前
Java集合框架深度解析:List、Set与Map的核心区别与应用指南
java·开发语言·list
计算机学姐32 分钟前
基于Asp.net的教学管理系统
vue.js·windows·后端·sqlserver·c#·asp.net·visual studio
Asthenia041239 分钟前
TCP的阻塞控制算法:无控制随便发/固定窗口/慢启动+阻塞避免/快恢复/TCP Cubic/BBR
后端
A boy CDEF girl1 小时前
【JavaEE】定时器
java·java-ee
AntBlack1 小时前
Python 打包笔记 : 你别说 ,PyStand 确实简单易上手
后端·python·创业