1. 防止参数值被篡改
当我们开发了一款产品,需要提供一些接口给第三方调用时,我们该如何防止这个接口被恶意请求呢?
解决方案:给这个请求再添加一个参数**key**
,用来标识唯一的使用者,由我们提供,任何人想要请求该接口时就要向我们申请这个key,这样我们就可以对调用该接口的人进行掌控了,如何使用者恶意请求,我们就可以对这个key进行限制了。
但是,如果使用者的key泄露了,被其它不法分子利用,再请求接口时对参数值进行更改,该如何防范?
解决方案:给这个请求再添加一个参数**sign**
,它是由参数 + secret根据不可逆算法生成的,secret固定,不在网络中传输,当请求服务端时,服务端同样根据相同的不可逆算法和secret值进行生成sign,然后和客户端传过来的sign进行比较,如果相等,说明参数啥的都是没有被篡改的,如果不相等,就说明参数被篡改了。
案例:
@RestController
@RequestMapping("/v2")
public class TestController2 {
// #$@!g78tyjkweop?y*
@Value(("${app.secret}"))
private String secret;
/**
* 测试参数防篡改
*/
@GetMapping("/test")
public String test(String name, Integer age, String key, String sign) {
// 1.从数据库查询key校验是否合法
// do something
// 2. 校验sign
String generateSign = generateSign(name + age + secret);
if (Objects.equals(sign, generateSign)) {
return "校验正确";
}
return "校验错误";
}
public String generateSign(String str) {
StringBuilder sb = new StringBuilder();
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(str.getBytes(StandardCharsets.UTF_8));
byte[] digest = md5.digest();
for (byte b : digest) {
sb.append(String.format("%02x", b));
}
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
return sb.toString();
}
2、先测试下当参数是 name=zhangsan age=18时得到的sign值是多少(客户端在请求时按照和服务端相同的逻辑生成sign)
public static void main(String[] args) {
String name = "zhangsan";
int age = 18;
String secret = "#$@!g78tyjkweop?y*";
System.out.println(new TestController2().generateSign(name + age + secret));
// eacc3b7657080774bfa84182de70a0e9
}
3、测试:当name=zhangsan age=18时测试校验正确
当把age的值改为19时 测试校验错误
2. 防止重复请求
有时候客户端在请求的时候可能由于自己那边卡顿,没反应,发了相同的请求给客户端,但是请求已经发给服务端了并且把结果返回了,导致重复请求。
为了防止重复请求,我们可以规定某个接口在规定时间内只能请求一次,比如1分钟内只能请求一次,当接收到客户端的请求时,可以比如把请求的接口值和用户唯一id拼接成一个字符串作为key,value的话就随便定个,然后存入redis,并设置过期时间是1分钟,当接收到请求时,先去redis查看校验。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。