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时测试校验正确
 title=

当把age的值改为19时 测试校验错误

 title=

2. 防止重复请求

有时候客户端在请求的时候可能由于自己那边卡顿,没反应,发了相同的请求给客户端,但是请求已经发给服务端了并且把结果返回了,导致重复请求。
为了防止重复请求,我们可以规定某个接口在规定时间内只能请求一次,比如1分钟内只能请求一次,当接收到客户端的请求时,可以比如把请求的接口值和用户唯一id拼接成一个字符串作为key,value的话就随便定个,然后存入redis,并设置过期时间是1分钟,当接收到请求时,先去redis查看校验。


xiaochen8848
1 声望0 粉丝

学习探索中。