基于RequestBodyAdvice和ResponseBodyAdvice来实现spring中参数的加密和解密
在日常开发中,有时候我们经常需要和第三方接口打交道,有时候是我们调用别人的第三方接口,有时候是别人在调用我们的第三方接口,那么为了调用接口的安全性,一般都会对传输的数据进行加密操作,如果每个接口都由我们自己去手动加密和解密,那么工作量太大而且代码冗余。那么有没有简单的方法,借助 spring 提供的 RequestBodyAdvice 和 ResponseBodyAdvice 可以实现解密和加密操作。
需求:
1,后台方法上如果有@Encrypt注解和@RequestBody修饰的方法,需要进行参数的解密
2,后台方法上如果有@Encrypt注解和@ResponseBody修饰的方法,需要进行参数的加密
3,加密和解密规则
加密:对返回的值中增加-encrypt值
解密:对传入的值中删除-encrypt值
注:
1,@Encrypt 为自定义的一个注解。
2,此处为了简单,就使用删除或增加-encrypt这个,实际情况下可以使用复杂的加解密规则
前置知识:
RequestBodyAdvice:在 sping 4.2 新加入的一个接口,它可以使用在 @RequestBody 或 HttpEntity 修改的参数之前进行参数的处理,比如进行参数的解密。
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,测试参数的解密操作
可以看到:参数中的-encrypt 传递后后台被后台自动截取了,这样就类似于解密操作。
6,测试返回值的加密操作
可以看到:返回的值后面都有一个 -encrypt ,这样就实现了类似于加密操作。
基于RequestBodyAdvice和ResponseBodyAdvice来实现spring中参数的加密和解密的更多相关文章
- Spring 中参数名称解析 - ParameterNameDiscoverer
Spring 中参数名称解析 - ParameterNameDiscoverer Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.ht ...
- 探讨.NET Core中实现AES加密和解密以及.NET Core为我们提供了什么方便!
前言 对于数据加密和解密每次我都是从网上拷贝一份,无需有太多了解,由于在.net core中对加密和解密目前全部是统一了接口,只是做具体的实现,由于遇到过问题,所以将打算基本了解下其原理,知其然足矣, ...
- JAVA中AES对称加密和解密
AES对称加密和解密 package demo.security; import java.io.IOException; import java.io.UnsupportedEncodingExce ...
- JAVA中AES对称加密和解密以及与Python兼容
引言:本文主要解决Java中用AES加密及解密,同时可通过Python脚本对Java加密后的字符进行解密的操作. 由于近期工作中用到需要使用Java对一串密钥进行加密,并且后台通过Python语言读取 ...
- spring中 的MD5 加密
//对密码进行加密(不需要使用其他Md5工具 .spring中有 在digestUtils) String password = DigestUtils.md5DigestAsHex( ...
- OPENSSL安装 以及使用openssl中的AES加密和解密
OPENSSL安装:(VS) 1:第一步和所有的软件安装一样. 2:将OPENSSL中INLUCDE 和 LIB 分别拷贝到VS中VC的INLUCDE 和LIB目录下(我的机器上的目录是:C:\Pro ...
- asp.net中实现MD5加密、解密的方法
这个MD5加密.解密的方法会使用即可. 使用时的代码备忘:Response.Write(FormsAuthentication.HashPasswordForStoringInConfigFile(& ...
- js中实现base64加密、解密
//base64加密 解密 /* //1.加密 var result = Base.encode('125中文'); //--> "MTI15Lit5paH" //2.解密 ...
- Spring中的面向切面编程(AOP)简介
一.什么是AOP AOP(Aspect-Oriented Programming, 面向切面编程): 是一种新的方法论, 是对传统 OOP(Object-Oriented Programming, 面 ...
随机推荐
- 在springboot pom文件配置过程,`spring-boot-maven-plugin`配置出错的问题解决及配置过程出现问题的一些思考
在springboot pom文件配置过程,spring-boot-maven-plugin配置出错的问题解决及配置过程出现问题的一些思考 解决方法一: 也是最简单的方法,可能是maven没有来得及导 ...
- java的split方法中的regex参数
我们需要以|进行分割,为了匹配|本身,正则中采用\|进行转义,而Java中\也表示转义,从java到正则需要必须使用\\|进行转义,即split中的\\表示正则的转义.
- 洛谷P1094——纪念品分组(简单贪心)
https://www.luogu.org/problem/show?pid=1094 题目描述 元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作.为使得参加晚会的同学所获得 的纪念品价值相对均 ...
- 使用manacher算法解决最长回文子串问题
要解决的问题 求一个字符串最长回文子串是什么.且时间复杂度 O(N) 具体描述可参考: LeetCode_5_最长回文子串 LintCode_200_最长回文子串 暴力解法 以每个字符为中心向左右两边 ...
- 【PHP数据结构】链表的其它形式
在上篇文章中,我们已经说过了链表除了简单的那一种单向链表外,还有其它的几种形式.当然,这也是链表这种结构的一大特点,非常地灵活和方便.我们简单的想一想,如果让最后一个节点的 next 指回第一个节点, ...
- symfony的几个请求变量和方法
请求变量 // 全部变量 $request->query->all(); // 指定变量 $request->query->get('abc'); 请求方式 $request- ...
- JDBC-1(概述&建立)
基于宋红康老师所讲JDBC所作笔记 1.JDBC概述 1.1 数据持久化 持久化:将数据保持到可掉电式存储设备中以供之后使用. 数据持久化意味着将内存中的数据保存到硬盘上加以固化,实现过程大多通过各种 ...
- php curl 发送post请求
PHP curl_init函数 resource curl_init ([ string $url = NULL ] ) 初始化一个新的会话,返回一个cURL句柄,供curl_setopt(), cu ...
- 制作python程序windows安装包(飞机大战源码)
本文以飞机大战源码为例: 1.首先使用pyinstaller -w xxx.py打包 -w的意思是不显示命令行:飞机大战源码由多个.py文件以及一些图片,音乐文件组成,我们将main.py打包, ...
- P3348-[ZJOI2016]大森林【LCT】
正题 题目链接:https://www.luogu.com.cn/problem/P3348 题目大意 有\(n\)棵树开始只有一个编号为\(1\)的节点且为标记点.\(m\)次操作要求支持 在\(l ...