后端与系统架构3357 字

充值接口被薅羊毛,老板让我做接口加密

·全库 564 / 611

《充值接口被薅羊毛,老板让我做接口加密》共 0.3 万字,通篇围绕 向量、安全、需求、场景 展开,归在「后端与系统架构」这一层。

覆盖向量安全需求场景面试

适合给 AI 系统搭底座、要管得住的人

目录骨架(4 节)
  1. 一、接口为什么要加密
  2. 二、加密思路
  3. 三、代码实现
  4. 四、总结

示例代码

📎 附件:encrypt-demo.zip(zip, 122KB)

原文链接:https://www.yuque.com/attachments/yuque/0/2024/zip/2424104/1715734300997-2d09ac7c-110c-4eeb-b07d-3635f7d3fd95.zip

jdk版本:1.8.0_181

​

本次分享内容

  1. 接口为什么要加密
  2. 前后端加密流程
  3. 加密算法(RAS非对称加密+AES对称加密)

一、接口为什么要加密

接口加密传输,主要作用:

  • 敏感数据防止泄漏、
  • 保护隐私、
  • 防伪装攻击、
  • 防篡改攻击、
  • 防重放攻击
  • 等等…
  • 4个字概括:保护数据!

当然不是说接口加密后,就能完完全全的保护我们的数据,但至少能防一部分人拿到我们的数据。

二、加密思路

1、加密简介

加密算法有很多,在能加密又能解密的算法可分为:

  • 非对称加密算法,常见:RSA、DSA、ECC 特点:算法复杂,加解密速度慢,但安全性高,一般与对称加密结合使用(对称加密对内容加密,非对称对对称所使用的密钥加密)

RSA:非对称加密aesKey,编码为Base64,公钥加密,私钥解密:防止aesKey泄密,导致业务数据被破译

参考资料:RSA加密算法原理 https://blog.csdn.net/a745233700/article/details/102341542

  • 对称加密算法,常见:AES、3DES、DES、Blowfish、IDEA、RC5、RC6 特点:加密解密效率高,速度快,适合进行大数据量的加解密

AES:对称加密业务数据,编码为Base64:防止敏感数据明文传输

参考资料:AES 加密算法原理详解 https://blog.csdn.net/u012581020/article/details/131246733

AES向量:IV可以有效提升安全性,但是在实际的使用场景中,它不能像密钥KEY那样直接保存在配置文件或固定写死在代码中,一般正确的处理方式为:在加密端将IV设置为一个16位的随机值,然后和加密文本一起返给解密端即可。

​

2、加密流程

思路:
假设现在客户端是A,服务端是B,现在A要去B请求接口

  • 1、A要向B发送信息,A和B都要产生一对用于加密的非对称加密公私钥(AB各自生成自己的公私钥)
  • 2、A的私钥保密,A的公钥告诉B;B的私钥保密,B的公钥告诉A。(AB互换公钥)
  • 3、A要给B发送信息时,A用B的公钥加密信息,因为A知道B的公钥。(公钥加密只有私钥能解)
  • 4、A将这个消息发给B(已经用B的公钥加密消息)。
  • 5、B收到这个消息后,B用自己的私钥解密A的消息。其他人收到这个报文都无法解密,因为只有B才有B的私钥。

1.jpg

虽然这样就实现了接口的加密方式,但是呢,非对称加密的加解密速度相比对称加密速度很慢,当传输的数据很大时就更加明显了。
所以我们对称与非对称一起用,理解上面的流程之后,我们在其基础稍微改下:

  • 在A给B发信息的时候,随机生成一个对称加密的密钥,然后用刚生成的密钥加密信息,然后用B的公钥加密刚生成的对称密钥。
  • A把加密的两个信息发送给B。B收到数据之后,先用自己的私钥解开得到对称密钥,然后再用解开的对称密钥解开对称加密的信息,最终得到A传来的信息。

三、代码实现

  • 在当下Java还是SpringBoot为主流框架工作面试必备,今天还是以它来举例。
  • 加解密代码怎么写,这个时候网上已经有很多现成的库了,不用我们操心,我们想的是如何在接口加解密的时候不影响我们自己的业务,也就是不用更改我们已经写好的代码。
  • 很多人的第一反应应该就是AOP吧,对的没错可以使用AOP进行环绕增强。也可以使用@ControllerAdvice 对Controller进行增强(本文以它来做为例子)。
  • Spring 提供两个接口RequestBodyAdvice、ResponseBodyAdvice。实现它们,即可对Controller进行增强,第一个是在controller之前增强,第二个就是对controller 的返回值进行增强。
  • 在spring启动的时候会对RequestMappingHandlerAdapter的initControllerAdviceCache()方法进行初始化。会去把有@ControllerAdvice的类进行注入。

1、自定义类

下面就来实现上面的两个接口实现类代码

EncryptRequestAdvice.java
  • 这个类的功能就是在请求到controller之前就把前端传上来的数据解密好
  • 我们还要校验是否有必要解密
``java /** * 请求参数到controller之前的处理 */ @ControllerAdvice(basePackages = {"com.example.encrypt.controller"}) public class EncryptRequestAdvice implements RequestBodyAdvice { @Autowired private KeyConfig keyConfig; /** * 是否需要解码 */ private boolean isDecode; @Override public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) { // 方法或类上有注解 if (MethodUtils.hasMethodAnnotation(methodParameter,new Class[]{Encrypt.class, Decode.class})) { isDecode=true; // 这里返回true 才支持 return true; } return false; } @Override public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException { if(isDecode){ return new DecodeInputMessage(httpInputMessage, keyConfig); } return httpInputMessage; } @Override public Object afterBodyRead(Object obj, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) { // 这里就是已经读取到body了,obj就是 return obj; } @Override public Object handleEmptyBody(Object obj, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) { // body 为空的时候调用 return obj; } } ``

资料里没有你的场景?

把你手上的数据和想解决的那个环节发上来,我们按具体情况回,不复述方法论。

发布需求