Api接口幂等设计

1,Api接口幂等设计,也就是要保证数据的唯一性,不允许有重复。

     例如:rpc 远程调用,因为网络延迟,出现了调用了2次的情况。

                表单连续点击,出现了重复提交。

                接口暴露之后,会被模拟请求工具(Jemter等)进行攻击。

2,怎么样保证接口幂等设计呢?

      可以使用Token方式,每次调用Api 接口(提交表单)之前,会调用api生成token,并将token给客户端保存,redis里面也保存token,redis 可以设置有效时长,约15-60 分钟

      当提交表单的时候,请求头里面要携带token,将请求头里面的token 拿出来和redis 里面的token进行比较,redis 里面有token,则表单提交,同时,删除token,redis 里面没有,则表单不提交。

3,调用index 方法的时候,生成token,客户端保存,点击提交,调用postIndex 接口前,token 验证

4,安装redis

5, 基于redis 写个redis 缓存token

package com.aiyuesheng.util;

import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

@Component
public class BaseRedisService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public void setString(String key, Object data, Long timeout) {
        if (data instanceof String) {
            String value = (String) data;
            stringRedisTemplate.opsForValue().set(key, value);
        }
        if (timeout != null) {
            stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);
        }
    }

    public Object getString(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    public void delKey(String key) {
        stringRedisTemplate.delete(key);
    }

}

 

package com.aiyuesheng.util;

import java.util.UUID;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class RedisToken {
    @Autowired
    private BaseRedisService baseRedisService;

    private static final long TIMEOUT = (60 * 60 * 60);

    public String setToken() {
        String token = System.currentTimeMillis() + "" + UUID.randomUUID();
        baseRedisService.setString(token, token, TIMEOUT);
        return token;
    }

    public String getToken(String tokenKey) {
        if(!StringUtils.isEmpty((String) baseRedisService.getString(tokenKey))){
            return (String) baseRedisService.getString(tokenKey);
        }
        return "";
    }
}

6,每次进行对比下。。。验证

 

posted @ 2019-07-29 21:36  Chris,Cai  阅读(1040)  评论(0编辑  收藏  举报