【架构实战】API接口防刷与限流策略
一、接口防刷概述接口防刷是保护系统安全的重要手段常见攻击暴力破解密码恶意爬虫刷接口抽奖、秒杀CC攻击二、限流算法1. 计数器算法ComponentpublicclassCounterRateLimiter{publicbooleantryAcquire(Stringkey,intlimit,intwindow){StringredisKeyratelimit:key;LongcountredisTemplate.opsForValue().increment(redisKey);if(count1){redisTemplate.expire(redisKey,window,TimeUnit.SECONDS);}returncountlimit;}}2. 滑动窗口算法ComponentpublicclassSlidingWindowRateLimiter{publicbooleantryAcquire(Stringkey,intlimit,intwindow){longnowSystem.currentTimeMillis();StringredisKeyratelimit:sliding:key;// 移除窗口外的请求redisTemplate.opsForZSet().removeRangeByScore(redisKey,0,now-window*1000);// 当前请求数LongcountredisTemplate.opsForZSet().zCard(redisKey);if(countlimit){returnfalse;}// 添加当前请求redisTemplate.opsForZSet().add(redisKey,now,now);redisTemplate.expire(redisKey,window*2,TimeUnit.SECONDS);returntrue;}}3. 令牌桶算法ComponentpublicclassTokenBucketRateLimiter{publicbooleantryAcquire(Stringkey,intbucketSize,intrefillRate){StringredisKeytokenbucket:key;// 获取令牌LongtokensredisTemplate.opsForValue().decrement(redisKey:tokens);if(tokensnull){// 初始化令牌桶redisTemplate.opsForValue().set(redisKey:tokens,bucketSize-1);redisTemplate.opsForValue().set(redisKey:last,System.currentTimeMillis());returntrue;}if(tokens0){// 令牌不足returnfalse;}returntrue;}}三、分布式限流1. Lua脚本限流ComponentpublicclassLuaRateLimiter{privatestaticfinalStringSCRIPT local key KEYS[1] local limit tonumber(ARGV[1]) local window tonumber(ARGV[2]) local current redis.call(INCR, key) if current 1 then redis.call(EXPIRE, key, window) end if current limit then return 0 end return 1 ;publicbooleantryAcquire(Stringkey,intlimit,intwindow){DefaultRedisScriptLongscriptnewDefaultScript();script.setScriptText(SCRIPT);LongresultredisTemplate.execute(script,Collections.singletonList(key),String.valueOf(limit),String.valueOf(window));returnresult!nullresult1;}}2. Sentinel限流ServicepublicclassSentinelRateLimiter{SentinelResource(valuegetOrder,blockHandlerblockHandler)publicOrdergetOrder(LongorderId){returnorderService.getById(orderId);}publicOrderblockHandler(LongorderId,BlockExceptione){thrownewBusinessException(请求过于频繁请稍后重试);}}// 配置限流规则ConfigurationpublicclassSentinelConfig{PostConstructpublicvoidinitRules(){ListFlowRulerulesnewArrayList();FlowRulerulenewFlowRule();rule.setResource(getOrder);rule.setGrade(RuleConstant.FLOW_GRADE_QPS);rule.setCount(100);// 每秒100次rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);rules.add(rule);FlowRuleManager.loadRules(rules);}}四、接口防刷策略1. 签名验证ComponentpublicclassSignValidator{Value(${app.secret})privateStringappSecret;publicbooleanvalidateSign(MapString,Stringparams,Stringsign){// 1. 排序参数StringsortedParamsparams.entrySet().stream().filter(e-!e.getKey().equals(sign)).sorted(Map.Entry.comparingByKey()).map(e-e.getKey()e.getValue()).collect(Collectors.joining());// 2. 拼接密钥StringsignStrsortedParamskeyappSecret;// 3. MD5签名StringcalculatedSignMD5(signStr).toUpperCase();returncalculatedSign.equals(sign.toUpperCase());}}2. 时间戳防重放ComponentpublicclassTimestampValidator{privatestaticfinallongMAX_TIMESTAMP_DIFF300000;// 5分钟publicbooleanvalidateTimestamp(longtimestamp){longnowSystem.currentTimeMillis();longdiffMath.abs(now-timestamp);returndiffMAX_TIMESTAMP_DIFF;}}3. 唯一请求IDComponentpublicclassIdempotentChecker{publicbooleancheck(StringrequestId){Stringkeyidempotent:requestId;BooleanresultredisTemplate.opsForValue().setIfAbsent(key,1,5,TimeUnit.MINUTES);returnBoolean.TRUE.equals(result);}}五、验证码防护1. 图形验证码ServicepublicclassCaptchaService{publicCaptchagenerateCaptcha(){// 生成随机字符串StringcodegenerateRandomCode(4);// 生成图片BufferedImageimagegenerateImage(code);// 生成唯一IDStringcaptchaIdUUID.randomUUID().toString();// 存入RedisredisTemplate.opsForValue().set(captcha:captchaId,code.toLowerCase(),5,TimeUnit.MINUTES);returnnewCaptcha(captchaId,image);}publicbooleanverify(StringcaptchaId,Stringcode){StringcachedCode(String)redisTemplate.opsForValue().get(captcha:captchaId);if(cachedCodenull){returnfalse;}booleanvalidcachedCode.equalsIgnoreCase(code);if(valid){redisTemplate.delete(captcha:captchaId);}returnvalid;}}2. 短信验证码ServicepublicclassSmsCodeService{publicvoidsendSmsCode(Stringphone){// 检查发送频率StringsendKeysms:send:phone;LongsendCountredisTemplate.opsForValue().increment(sendKey);if(sendCount!nullsendCount5){thrownewBusinessException(发送过于频繁请1小时后再试);}if(sendCount1){redisTemplate.expire(sendKey,1,TimeUnit.HOURS);}// 生成6位验证码StringcodeString.format(%06d,newRandom().nextInt(1000000));// 存入RedisStringcodeKeysms:code:phone;redisTemplate.opsForValue().set(codeKey,code,5,TimeUnit.MINUTES);// 发送短信smsClient.send(phone,验证码code);}}六、IP限流ComponentpublicclassIPRateLimiter{publicbooleantryAcquire(Stringip,Stringapi,intlimit,intwindow){Stringkeyip:ratelimit:ip:api;LongcountredisTemplate.opsForValue().increment(key);if(count1){redisTemplate.expire(key,window,TimeUnit.SECONDS);}if(countlimit){// 封禁IPblockIP(ip);returnfalse;}returntrue;}privatevoidblockIP(Stringip){StringblockKeyip:block:ip;redisTemplate.opsForValue().set(blockKey,1,1,TimeUnit.HOURS);}}七、总结接口防刷是系统安全的重要组成限流算法计数器、滑动窗口、令牌桶分布式限流Lua脚本、Sentinel签名验证防止请求被篡改验证码防止机器攻击最佳实践多层限流网关应用数据库根据业务场景选择限流策略做好监控和告警个人观点仅供参考
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2503910.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!