加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_泰州站长网 (http://www.0523zz.com/)- 视觉智能、AI应用、CDN、行业物联网、智能数字人!
当前位置: 首页 > 服务器 > 安全 > 正文

如何优雅的达成 Spring Boot 接口参数加密解密?

发布时间:2022-07-01 15:10:58 所属栏目:安全 来源:互联网
导读:因为有小伙伴刚好问到这个问题,松哥就抽空撸一篇文章和大家聊聊这个话题。 加密解密本身并不是难事,问题是在何时去处理?定义一个过滤器,将请求和响应分别拦截下来进行处理也是一个办法,这种方式虽然粗暴,但是灵活,因为可以拿到一手的请求参数和响应数
  因为有小伙伴刚好问到这个问题,松哥就抽空撸一篇文章和大家聊聊这个话题。
 
  加密解密本身并不是难事,问题是在何时去处理?定义一个过滤器,将请求和响应分别拦截下来进行处理也是一个办法,这种方式虽然粗暴,但是灵活,因为可以拿到一手的请求参数和响应数据。不过 SpringMVC 中给我们提供了 ResponseBodyAdvice 和 RequestBodyAdvice,利用这两个工具可以对请求和响应进行预处理,非常方便。
 
  所以今天这篇文章有两个目的:
 
  分享参数/响应加解密的思路。
  分享 ResponseBodyAdvice 和 RequestBodyAdvice 的用法。
  好了,那么接下来就不废话了,我们一起来看下。
 
  1.开发加解密 starter
 
  为了让我们开发的这个工具更加通用,也为了复习一下自定义 Spring Boot Starter,这里我们就将这个工具做成一个 stater,以后在 Spring Boot 项目中直接引用就可以。
 
  首先我们创建一个 Spring Boot 项目,引入 spring-boot-starter-web 依赖:
 
  复制
  6.
  因为我们这个工具是为 Web 项目开发的,以后必然使用在 Web 环境中,所以这里添加依赖时 scope 设置为 provided。
 
  依赖添加完成后,我们先来定义一个加密工具类备用,加密这块有多种方案可以选择,对称加密、非对称加密,其中对称加密又可以使用 AES、DES、3DES 等不同算法,这里我们使用 Java 自带的 Cipher 来实现对称加密,使用 AES 算法:
 
  复制
  public class AESUtils {
   
      private static final String AES_ALGORITHM = "AES/ECB/PKCS5Padding";
   
      // 获取 cipher
      private static Cipher getCipher(byte[] key, int model) throws Exception {
          SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
          Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
          cipher.init(model, secretKeySpec);
          return cipher;
      }
   
      // AES加密
      public static String encrypt(byte[] data, byte[] key) throws Exception {
          Cipher cipher = getCipher(key, Cipher.ENCRYPT_MODE);
          return Base64.getEncoder().encodeToString(cipher.doFinal(data));
      }
   
      // AES解密
      public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
          Cipher cipher = getCipher(key, Cipher.DECRYPT_MODE);
          return cipher.doFinal(Base64.getDecoder().decode(data));
      }
  }
   这个工具类比较简单,不需要多解释。需要说明的是,加密后的数据可能不具备可读性,因此我们一般需要对加密后的数据再使用 Base64 算法进行编码,获取可读字符串。换言之,上面的 AES 加密方法的返回值是一个 Base64 编码之后的字符串,AES 解密方法的参数也是一个 Base64 编码之后的字符串,先对该字符串进行解码,然后再解密。
 
  接下来我们封装一个响应工具类备用,这个大家如果经常看松哥视频已经很了解了:
 
  复制
  public class RespBean {
      private Integer status;
      private String msg;
      private Object obj;
   
      public static RespBean build() {
          return new RespBean();
      }
           return new RespBean(500, msg, obj);
      }
   
      private RespBean() {
       public Integer getStatus() {
          return status;
      }
   
      public RespBean setStatus(Integer status) {
          this.status = status;
          return this;
      }
   
      public String getMsg() {
          return msg;
      }
   
      public RespBean setMsg(String msg) {
          this.msg = msg;
          return this;
      }
   
      public Object getObj() {
          return obj;
      }
   
      public RespBean setObj(Object obj) {
          this.obj = obj;
          return this;
      }
  }
   接下来我们定义两个注解 @Decrypt 和 @Encrypt:
 
  复制
  @Retention(RetentionPolicy.RUNTIME)
  @Target({ElementType.METHOD,ElementType.PARAMETER})
  public @interface Decrypt {
  }
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.METHOD)
  public @interface Encrypt {
  }
   这两个注解就是两个标记,在以后使用的过程中,哪个接口方法添加了 @Encrypt 注解就对哪个接口的数据加密返回,哪个接口/参数添加了 @Decrypt 注解就对哪个接口/参数进行解密。这个定义也比较简单,没啥好说的,需要注意的是 @Decrypt比 @Encrypt 多了一个使用场景就是 @Decrypt 可以用在参数上。
 
  考虑到用户可能会自己配置加密的 key,因此我们再来定义一个 EncryptProperties 类来读取用户配置的 key:
 
  复制
  @ConfigurationProperties(prefix = "spring.encrypt")
  public class EncryptProperties {
      private final static String DEFAULT_KEY = "www.itboyhub.com";
      private String key = DEFAULT_KEY;
   
      public String getKey() {
          return key;
      }
   
      public void setKey(String key) {
          this.key = key;
      }
  }
   这里我设置了默认的 key 是 www.itboyhub.com,key 是 16 位字符串,松哥这个网站地址刚好满足。以后如果用户想自己配置 key,只需要在 application.properties 中配置 spring.encrypt.key=xxx 即可。
 
  所有准备工作做完了,接下来就该正式加解密了。
 
  因为松哥这篇文章一个很重要的目的是想和大家分享 ResponseBodyAdvice 和 RequestBodyAdvice 的用法,RequestBodyAdvice 在做解密的时候倒是没啥问题,而 ResponseBodyAdvice 在做加密的时候则会有一些局限,不过影响不大,还是我前面说的,如果想非常灵活的掌控一切,那还是自定义过滤器吧。这里我就先用这两个工具来实现了。
 
  另外还有一点需要注意,ResponseBodyAdvice 在你使用了 @ResponseBody 注解的时候才会生效,RequestBodyAdvice 在你使用了 @RequestBody 注解的时候才会生效,换言之,前后端都是 JSON 交互的时候,这两个才有用。不过一般来说接口加解密的场景也都是前后端分离的时候才可能有的事。

(编辑:云计算网_泰州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读