通过Interceptor以及Redis实现接口访问防刷
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| /** * 接口防刷 */ @Slf4j public class AccessLimintInterceptor implements HandlerInterceptor {
@Resource private RedisTemplate<String, Object> redisTemplate;
/** * 多长时间内 */ @Value("${interfaceAccess.second}") private final Long second = 10L;
/** * 访问次数 */ @Value("${interfaceAccess.time}") private final Long time = 3L;
/** * 禁用时长--单位/秒 */ @Value("${interfaceAccess.lockTime}") private final Long lockTime = 60L;
@Value("${interfaceAccess.methodUri}") private final String methodUri = "";
/** * 锁住时的key前缀 */ public static final String LOCK_PREFIX = "METHOD_LOCK:";
/** * 统计次数时的key前缀 */ public static final String COUNT_PREFIX = "METHOD_LOCK_COUNT:";
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String uri = request.getRequestURI(); String ip = request.getRemoteAddr(); // 这里忽略代理软件方式访问,默认直接访问,也就是获取得到的就是访问者真实ip地址
List<String> methodUriList = Arrays.asList(methodUri.split(",")); if (!methodUriList.contains(uri)) { return true; }
String lockKey = LOCK_PREFIX + ip + uri; Object isLock = redisTemplate.opsForValue().get(lockKey); if (Objects.isNull(isLock)) { // 还未被禁用 String countKey = COUNT_PREFIX + ip + uri; Object count = redisTemplate.opsForValue().get(countKey); if (Objects.isNull(count)) { // 首次访问 redisTemplate.opsForValue().set(countKey, 1, second, TimeUnit.SECONDS); } else { // 此用户前一点时间就访问过该接口 if ((Integer) count < time) { // 放行,访问次数 + 1 redisTemplate.opsForValue().increment(countKey); } else { log.info("{}禁用访问{}", ip, uri); // 禁用 redisTemplate.opsForValue().set(lockKey, 1, lockTime, TimeUnit.SECONDS); // 删除统计 redisTemplate.delete(countKey); throw new RuntimeException("访问过于频繁"); } } } else { // 此用户访问此接口已被禁用 throw new RuntimeException("访问过于频繁!"); } return true; } }
|
application中添加
1 2 3 4 5 6
| # 接口防刷配置,规定时间内,可以访问多少次 interfaceAccess: second: 60 # 时间,单位秒 time: 10 # 次数 lockTime: 60 #限制时长,单位秒 methodUri: /appointment/api/getDepts #限制的接口地址,使用英文逗号【,】分隔
|
最后更新时间: