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;
    }
}
相关推荐
陈随易1 小时前
FFmpeg 9.0 发布,代号 Lei,音视频处理再升级
前端·后端·程序员
凌虚4 小时前
面向 MySQL 用户的 PostgreSQL 快速上手指南
数据库·后端·架构
都叫我大帅哥4 小时前
Java JJWT 完全指南:从入门到生产级实践
java
IT_陈寒5 小时前
Vite静态资源引用这个坑我踩得有点疼
前端·人工智能·后端
前端开发张小七5 小时前
Java 学习笔记 · 第一课:基础语法与核心概念
java·后端
海盗12346 小时前
微软技术周报 ——2026-08-03
后端·python·microsoft·c#·.netcore
沙湖遇雨6 小时前
6. Pipeline 的生命周期
后端
青青子衿悠悠我心6 小时前
TRAE Work让财务月底对账3小时变5分钟
后端
创安电气研究所6 小时前
用TypeScript给Modbus设备做一层适配器
后端
妙码生花6 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(五十):增加管理员角色组管理
前端·后端·ai编程