欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于RequestBodyAdvice和ResponseBodyAdvice来实现spring中参数的加密和解密

程序员文章站 2022-05-28 13:44:13
...

    在日常开发中,有时候我们经常需要和第三方接口打交道,有时候是我们调用别人的第三方接口,有时候是别人在调用我们的第三方接口,那么为了调用接口的安全性,一般都会对传输的数据进行加密操作,如果每个接口都由我们自己去手动加密和解密,那么工作量太大而且代码冗余。那么有没有简单的方法,借助 spring 提供的  RequestBodyAdviceResponseBodyAdvice 可以实现解密和加密操作。

 

需求:

     1,后台方法上如果有@Encrypt注解和@RequestBody修饰的方法,需要进行参数的解密    

     2,后台方法上如果有@Encrypt注解和@ResponseBody修饰的方法,需要进行参数的加密

     3,加密和解密规则

           加密:对返回的值中增加-encrypt值

           解密:对传入的值中删除-encrypt值

     注:

          1,@Encrypt 为自定义的一个注解。

          2,此处为了简单,就使用删除或增加-encrypt这个,实际情况下可以使用复杂的加解密规则

 

前置知识:

RequestBodyAdvice:在 sping 4.2 新加入的一个接口,它可以使用在 @RequestBodyHttpEntity 修改的参数之前进行参数的处理,比如进行参数的解密

ResponseBodyAdvice:在 spring 4.1 新加入的一个接口,在消息体被HttpMessageConverter写入之前允许Controller 中 @ResponseBody修饰的方法或ResponseEntity调整响应中的内容,比如进行相应的加密

 

功能实现:

1,编写加密注解类(Encrypt)

/**
 * 进行参数加密和解密
 *
 * @author huan.fu
 * @date 2018/9/28 - 16:08
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Encrypt {
}

 2,编写RequestBodyAdvice接口实现类,实现数据的解密操作

 

/**
 * 解密数据
 *
 * @author huan.fu
 * @date 2018/9/28 - 16:09
 */
@Slf4j
@RestControllerAdvice
public class ParamEncryptRequestBodyAdvice implements RequestBodyAdvice {

	@Override
	public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
		return methodParameter.hasParameterAnnotation(RequestBody.class);
	}

	@Override
	public Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
		return o;
	}

	@Override
	public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
		return new HttpInputMessage() {
			@Override
			public InputStream getBody() throws IOException {
				log.info("此处进行解密数据");
				return new ByteArrayInputStream(IOUtils.toString(httpInputMessage.getBody()).replace("-encrypt", "").getBytes(StandardCharsets.UTF_8));
			}

			@Override
			public HttpHeaders getHeaders() {
				return httpInputMessage.getHeaders();
			}
		};
	}

	@Override
	public Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
		return o;
	}
}

 3,编写ResponseBodyAdvice接口实现类,实现数据的加密操作

/**
 * 加密数据
 *
 * @author huan.fu
 * @date 2018/9/28 - 16:19
 */
@Slf4j
@RestControllerAdvice
public class ParamEncryptResponseBodyAdvice implements ResponseBodyAdvice {

	private final ObjectMapper objectMapper = new ObjectMapper();

	@Override
	public boolean supports(MethodParameter returnType, Class converterType) {
		return returnType.hasMethodAnnotation(ResponseBody.class);
	}

	@Override
	public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
		log.info("此处进行加密数据");
		if (null != body) {
			try {
				Map map = objectMapper.readValue(objectMapper.writeValueAsString(body), Map.class);
				map.forEach((key, value) -> map.put(key, value + "-encrypt"));
				return map;
			} catch (IOException e) {
				log.error("加密数据失败.", e);
			}
		}

		return body;
	}
}

 4,编写控制层进行测试

/**
 * 用户信息控制器
 *
 * @author huan.fu
 * @date 2018/9/28 - 15:55
 */
@RestController
@RequestMapping("user-info")
@Slf4j
public class UserInfoController {

	/**
	 * 添加用户实现返回值加密
	 *
	 * @param userInfo
	 * @return
	 */
	@PostMapping("add")
	@Encrypt
	public UserInfo add(@RequestBody UserInfo userInfo) {
		log.info("添加新用户:[{}]", userInfo);
		return userInfo;
	}

	/**
	 * 修改实现获取的参数进行解密
	 *
	 * @param userInfo
	 * @return
	 */
	@PostMapping("update")
	public UserInfo update(@Encrypt @RequestBody UserInfo userInfo) {
		log.info("修改用户信息:[{}]", userInfo);
		return userInfo;
	}
}

 5,测试参数的解密操作
基于RequestBodyAdvice和ResponseBodyAdvice来实现spring中参数的加密和解密
            
    
    博客分类: spring springRequestBodyAdviceResponseBodyAdvice响应数据加解密
  可以看到:参数中的-encrypt 传递后后台被后台自动截取了,这样就类似于解密操作。

 6,测试返回值的加密操作
基于RequestBodyAdvice和ResponseBodyAdvice来实现spring中参数的加密和解密
            
    
    博客分类: spring springRequestBodyAdviceResponseBodyAdvice响应数据加解密
 可以看到:返回的值后面都有一个 -encrypt ,这样就实现了类似于加密操作。

 

 

 

 

 

  • 基于RequestBodyAdvice和ResponseBodyAdvice来实现spring中参数的加密和解密
            
    
    博客分类: spring springRequestBodyAdviceResponseBodyAdvice响应数据加解密
  • 大小: 1.1 MB
  • 基于RequestBodyAdvice和ResponseBodyAdvice来实现spring中参数的加密和解密
            
    
    博客分类: spring springRequestBodyAdviceResponseBodyAdvice响应数据加解密
  • 大小: 1.1 MB