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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| @Override public ResponseResult getMobileCode(String mobile) { if (!StringUtils.hasText(mobile)) { return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "手机号不能为空"); }
mobile = mobile.trim();
if (!mobile.matches("^1[3-9]\\d{9}$")) { return ResponseResult.errorResult(AppHttpCodeEnum.PHONE_FORMAT_ERROR); }
String clientIp = getClientIp(); ResponseResult limitResult = checkCodeLimit(mobile, clientIp); if (limitResult != null) { return limitResult; }
String code = generateCode(); String redisKey = saveCodeToRedis(mobile, code, clientIp);
try { aliyunSmsServiceImpl.sendVerificationCode(mobile, code); } catch (Exception e) { redisCache.deleteObject(redisKey); redisCache.deleteObject(String.format("admin:send:time:%s", mobile)); log.error("发送手机验证码失败, mobile={}, error={}", mobile, e.getMessage(), e); return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "验证码发送失败,请稍后重试"); }
return ResponseResult.okResult(); }
private String generateCode() { Random random = new Random(); return String.valueOf(random.nextInt(900000) + 100000); }
private String getClientIp() { String clientIp = "unknown"; try { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attributes != null) { HttpServletRequest request = attributes.getRequest(); clientIp = IpUtils.getIpAddr(request); } } catch (Exception e) { log.warn("获取客户端IP失败: {}", e.getMessage()); } return clientIp; }
private ResponseResult checkCodeLimit(String target, String clientIp) { String dayKey = String.format("admin:ip:limit:day:%s", clientIp); Integer dayCount = redisCache.getCacheObject(dayKey); if (dayCount != null && dayCount >= 50) { return ResponseResult.errorResult(AppHttpCodeEnum.IP_REQUEST_LIMIT, "系统检测到异常行为,请24小时后再试或联系管理员"); }
String sendTimeKey = String.format("admin:send:time:%s", target); String lastSendTime = redisCache.getCacheObject(sendTimeKey); if (StringUtils.hasText(lastSendTime)) { return ResponseResult.errorResult(AppHttpCodeEnum.SMS_SEND_FREQUENTLY, "验证码发送过于频繁,请1分钟后再试"); }
String minuteKey = String.format("admin:ip:limit:minute:%s", clientIp); Integer minuteCount = redisCache.getCacheObject(minuteKey); if (minuteCount != null && minuteCount >= 5) { return ResponseResult.errorResult(AppHttpCodeEnum.IP_REQUEST_LIMIT, "您的操作过于频繁,请1分钟后再试"); }
String hourKey = String.format("admin:ip:limit:hour:%s", clientIp); Integer hourCount = redisCache.getCacheObject(hourKey); if (hourCount != null && hourCount >= 20) { return ResponseResult.errorResult(AppHttpCodeEnum.IP_REQUEST_LIMIT, "您的操作过于频繁,请1小时后再试"); }
return null; }
private String saveCodeToRedis(String target, String code, String clientIp) { String redisKey = String.format("admin:code:%s", target); String sendTimeKey = String.format("admin:send:time:%s", target); String minuteKey = String.format("admin:ip:limit:minute:%s", clientIp); String hourKey = String.format("admin:ip:limit:hour:%s", clientIp); String dayKey = String.format("admin:ip:limit:day:%s", clientIp);
Integer minuteCount = redisCache.getCacheObject(minuteKey); Integer hourCount = redisCache.getCacheObject(hourKey); Integer dayCount = redisCache.getCacheObject(dayKey);
redisCache.setCacheObject(redisKey, code, 5, TimeUnit.MINUTES); redisCache.setCacheObject(sendTimeKey, String.valueOf(System.currentTimeMillis()), 1, TimeUnit.MINUTES); redisCache.setCacheObject(minuteKey, minuteCount == null ? 1 : minuteCount + 1, 1, TimeUnit.MINUTES); redisCache.setCacheObject(hourKey, hourCount == null ? 1 : hourCount + 1, 1, TimeUnit.HOURS); redisCache.setCacheObject(dayKey, dayCount == null ? 1 : dayCount + 1, 1, TimeUnit.DAYS);
return redisKey; }
|