当前位置:   article > 正文

微服务巧用Aop,使用RequestBodyAdvice对请求参数加密,项目全局增强Api接口安全性

微服务巧用Aop,使用RequestBodyAdvice对请求参数加密,项目全局增强Api接口安全性

大家好,我是程序员大猩猩。

在我们日常开发中,通常不会考虑到Api的安全性,但是在运维部署时,如果是小公司,大可能的配置ssl文件是免费的,安全性并不是很高,市场上有很多的工具可以简单的进行破解,这大大的增加了我们Api接口的风险值

如果不管不问,我们的Api接口就像在互联网上裸奔一样,专业破解方就像看我们的API没穿裤衩子一样,随意的更改我们的请求与回放。

当领导找到我们时,是不是内心遭受了百万暴击一样,满腹在骂娘!~~

我TM我的接口没有一点毛病,有攻击就加强服务器的安全组件,干什么说我技术不行,CAO~~~~

心里骂了半天,但是又有什么办法,领导又不懂代码,我们不是还得撸起袖子搞点安全系数高的代码来增强我们的Api。

那么如何更改呢?

1. 前端Json块使用约定俗成的加密盐进行对称加密。

2. 后端进行解密操作。

3. 后端对请求的返回Json块进行加密

4. 前端进行解密操作。

注:双方一定要约定一套有加密盐的对称加密方式最佳哦!~~

接下来,我们来完成后端部分的全局解密方法。

一、RequestBodyAdvice

RequestBodyAdvice是Spring框架中用于处理HTTP请求体的一个接口,它允许我们在控制器处理请求之前对请求体进行一些自定义操作。

这个接口通常用于对请求体进行校验、转换或者日志记录等操作。

RequestBodyAdvice接口提供了下面几个方法:

a. supports: 这个方法用于判断当前的RequestBodyAdvice是否适用于给定的控制器方法参数。

b. beforeBodyRead: 这个方法在请求体被读取并反序列化为对象之前调用,可以在这里对请求体进行预处理。

c. afterBodyRead: 这个方法在请求体被读取并反序列化为对象之后调用,可以在这里对反序列化后的对象进行后处理。

d.handleEmptyBody: 这个方法在请求没有请求体时调用,可以在这里提供默认值或者进行其他处理。

我们来重写上面的方法吧,只要是重写beforeBodyRead来实现。

二、beforeBodyRead

  1. /**
  2. * Invoked second before the request body is read and converted.
  3. *
  4. * @param inputMessage the request
  5. * @param parameter the target method parameter
  6. * @param targetType the target type, not necessarily the same as the method
  7. * parameter type, e.g. for {@code HttpEntity<String>}.
  8. * @param converterType the converter used to deserialize the body
  9. * @return the input request or a new instance, never {@code null}
  10. */
  11. @Override
  12. public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
  13. try {
  14. return new RequestHttpInputMessage(inputMessage, parameter);
  15. } catch (Exception e) {
  16. return inputMessage;
  17. }
  18. }

RequestHttpInputMessage是一个继承HttpInputMessage的自定义类。

三、HttpInputMessage获取API接口头和请求体

HttpInputMessage 它代表了一个 HTTP 输入消息,通常用于读取 HTTP 请求的正文,这个接口提供了对 HTTP 请求头和请求体的访问。

HttpInputMessage 接口定义了以下两个方法:

  1. getHeaders(): 返回一个不可变的 MultiValueMap<String, String>,包含了 HTTP 消息头的键值对。这些消息头可以包含如内容类型、内容长度、缓存控制等信息。

  2. getBody(): 返回一个 InputStream,通过这个流可以读取 HTTP 消息的正文。这通常用于读取客户端发送的数据,如 JSON 或 XML 格式的数据。

    注意:getBody是一次性的方法,当你使用了一次获取了InputStream之后,再使用此方法,是无法再次获取到的。为了规避此问题,我们应该使用如下代码块进行获取。

  1. final ByteArrayInputStream bais = new ByteArrayInputStream(readBytes(body));
  2. privatebyte[] readBytes(InputStream in) throws IOException {
  3. int buffSize = 1024;
  4. try (BufferedInputStream bis = new BufferedInputStream(in); ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize)) {
  5. byte[] temp = new byte[buffSize];
  6. int size;
  7. while ((size = bis.read(temp)) != -1) {
  8. out.write(temp, 0, size);
  9. }
  10. return out.toByteArray();
  11. }
  12. }

四、实现RequestHttpInputMessage

我们来实现一下这个RequestHttpInputMessage,主要在构造函数内进行解密即可。

  1. public RequestHttpInputMessage(HttpInputMessage inputMessage, MethodParameter parameter) throws Exception {
  2. this.headers = inputMessage.getHeaders();
  3. String encryptStr = easeString(IOUtils.toString(inputMessage.getBody(), StandardCharsets.UTF_8));
  4. // 解密
  5. String decrypt = AesEncryptUtils.decrypt(encryptStr);
  6. String replace = decrypt;
  7. log.info("RequestHttpInputMessage:{}", replace);
  8. // 特殊处理
  9. if (decrypt.contains("certImages")) {
  10. replace = decrypt.replace("\\", "");
  11. }
  12. // 解密后的请求块
  13. this.body = IOUtils.toInputStream(replace, StandardCharsets.UTF_8);
  14. }

AesEncryptUtils.decrypt属于请求块的解密方法。假如有特殊的请求,我们可以进行方法变通。最后更改请求块,然后将解密后的请求块发送给Controller了。

另外需要我自己的加密类,可以留言联系我获取,谢谢~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/621011
推荐阅读
相关标签
  

闽ICP备14008679号