有時需要對請求或返回的數據進行加密,那么SpringBoot就提供了支持,可對請求體進行處理,也可對響應體進行處理。
1.對請求體處理
對響應體進行處理,需要實現RequestBodyAdvice接口,重寫方法。
package com.zys.example.config; import lombok.extern.slf4j.Slf4j; import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpInputMessage; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; @Component @ControllerAdvice @Slf4j public class DecodeRequestBodyAdvice implements RequestBodyAdvice { @Override public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) { return true; } @Override public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) { //獲取請求頭信息 String header = httpInputMessage.getHeaders().getFirst("header"); log.info("獲取的請求頭header:{}", header); String body = null; try { // 從流中提取數據 InputStream is = httpInputMessage.getBody(); byte[] data = new byte[is.available()]; is.read(data); body = new String(data, StandardCharsets.UTF_8); log.info("請求的數據,{}", body); //對數據進行處理 } catch (IOException e) { e.printStackTrace(); } return new DecodedHttpInputMessage(httpInputMessage.getHeaders(), new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8))); } @Override public Object afterBodyRead(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) { return body; } @Override public Object handleEmptyBody(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) { return body; } static class DecodedHttpInputMessage implements HttpInputMessage { HttpHeaders headers; InputStream body; public DecodedHttpInputMessage(HttpHeaders headers, InputStream body) { this.headers = headers; this.body = body; } @Override public InputStream getBody() { return body; } @Override public HttpHeaders getHeaders() { return headers; } } }
需要注意是,其僅針對@RequestBody注解生效,也就是說要必須是POST請求,使用@RequestBody注解接收,才能執行上述的操作。否則不生效,如下:
@RestController public class TestController { @PostMapping("/test") public JSONObject get(@RequestBody JSONObject json) { return json; } }
使用了@ControllerAdvice,若不指定值,則會對所有的請求進行攔截並解密。若只對特定的接口進行攔截解密,則使用數組指定接口即可:
@ControllerAdvice({"/test"})
2.對響應體處理
對響應體進行處理,需要新建類,實現ResponseBodyAdvice接口,重寫方法。
package com.zys.example.config; import lombok.extern.slf4j.Slf4j; 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.stereotype.Component; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; @Component @ControllerAdvice @Slf4j public class EncodeResponseBodyAdvice implements ResponseBodyAdvice<Object> { @Override public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) { //若返回false則下面的配置不生效 return true; } @Override public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { //獲取請求頭信息,需要時獲取 String header = serverHttpRequest.getHeaders().getFirst("header"); log.info("獲取的請求頭header:{}",header); //body即是返回的數據,可對其進行處理后返回,如加密 return body; } }