Spring Boot 拦截 requestBody 和 reponseBody 做数据加密解密

803 阅读1分钟

Spring Boot 拦截 requestBody 解密请求数据

HelloRequestAdvice.java :

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

import org.springframework.core.MethodParameter;
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;

@ControllerAdvice
public class HelloRequestAdvice implements RequestBodyAdvice {
    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType,
        Class<? extends HttpMessageConverter<?>> converterType) {
        // 返回 true ,则会进行拦截处理。 返回 false ,则不会进行任何处理。
        return true;
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
        Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        // 返回处理 httpInputMessage 的 HttpInputMessage 对象
        return new HelloHttpInputMessage(httpInputMessage);
    }

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

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

HelloHttpInputMessage.java :
拦截请求内容进行处理(比如解密处理)。

import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

public class HelloHttpInputMessage implements HttpInputMessage {
    private HttpHeaders headers;
    private InputStream body;

    public HelloHttpInputMessage(HttpInputMessage inputMessage) throws IOException {
        String origionalBody = IOUtils.toString(inputMessage.getBody(), StandardCharsets.UTF_8.name());
        
        // 这里可进行处理(比如解密处理)
    	String newBody = origionalBody;
        
        this.body = IOUtils.toInputStream(newBody, StandardCharsets.UTF_8.name());
    }

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

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

Spring Boot 拦截 reponseBody 加密响应数据

HelloResponseAdvice.java :
拦截响应内容进行处理(比如加密处理)。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@ControllerAdvice
public class HelloResponseAdvice implements ResponseBodyAdvice<Object> {

    @Autowired
    private ObjectMapper mapper;
    
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { 
        // 注释的判断为 对于带有 ResponseBody 注解的处理进行拦截
        // return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
        // returnType.hasMethodAnnotation(ResponseBody.class));

        // 返回 true ,则会进行拦截处理。 返回 false ,则不会进行任何处理。
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
        Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        String value = null;
        try {
             value =  mapper.writeValueAsString(body);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
        
        // 这里可进行处理(比如加密处理)
        return value;
    }
}