Commit 0850d3ca authored by 技术部-任文超's avatar 技术部-任文超

1、改良log; 2、添加常量; 3、修正短信和语音获取的上限策略(原来是叠加计数效果,改为独立计数效果)

parent 170ab16e
...@@ -13,9 +13,11 @@ public interface Constants { ...@@ -13,9 +13,11 @@ public interface Constants {
String REDIS_CAPTCHA_KEY = "auth:"; String REDIS_CAPTCHA_KEY = "auth:";
String REDIS_PREFIX_VERIFICATION_CODE = "verificationCode_"; String REDIS_PREFIX_VERIFICATION_CODE = "verificationCode_";
//新版短信验证码计数 //新版短信验证码计数
String REDIS_SMS_IP_COUNT = "SMS_Ip_verification_code_count:";
String REDIS_SMS_CODE_COUNT = "SMS_Phone_verification_code_count:"; String REDIS_SMS_CODE_COUNT = "SMS_Phone_verification_code_count:";
String REDIS_SMS_DEVICE_COUNT = "SMS_Device_verification_code_count:"; String REDIS_SMS_DEVICE_COUNT = "SMS_Device_verification_code_count:";
//新版语音验证码计数 //新版语音验证码计数
String REDIS_VOICE_IP_COUNT = "Voice_Ip_verification_code_count:";
String REDIS_VOICE_CODE_COUNT = "Voice_Phone_verification_code_count:"; String REDIS_VOICE_CODE_COUNT = "Voice_Phone_verification_code_count:";
String REDIS_VOICE_DEVICE_COUNT = "Voice_Device_verification_code_count:"; String REDIS_VOICE_DEVICE_COUNT = "Voice_Device_verification_code_count:";
...@@ -26,41 +28,41 @@ public interface Constants { ...@@ -26,41 +28,41 @@ public interface Constants {
String X_AUTH_TOKEN = "x-auth-token"; String X_AUTH_TOKEN = "x-auth-token";
// -- Start -- IPV4安全策略常量组 // -- Start -- IPV4安全策略常量组
// 账密不匹配错误 - 按账号计数 /** 账密不匹配错误 - 按账号计数 */
String REDIS_PASSWORD_ERROR_COUNT = "password_error_count:"; String REDIS_PASSWORD_ERROR_COUNT = "password_error_count:";
// 账密不匹配错误 - 按IP计数 /** 账密不匹配错误 - 按IP计数 */
String REDIS_PASSWORD_ERROR_COUNT_FOR_IPV4 = "password_error_count_4_ipv4:"; String REDIS_PASSWORD_ERROR_COUNT_FOR_IPV4 = "password_error_count_4_ipv4:";
// 账密匹配成功 - 按IP计数 /** 账密匹配成功 - 按IP计数 */
String REDIS_PASSWORD_SUCCESS_COUNT_FOR_IPV4 = "password_success_count_4_ipv4:"; String REDIS_PASSWORD_SUCCESS_COUNT_FOR_IPV4 = "password_success_count_4_ipv4:";
// 账密安全策略 - 白名单 /** 账密安全策略 - 白名单 */
String IPV4_LOCK_WHITE = "lock_ipv4:white:"; String IPV4_LOCK_WHITE = "lock_ipv4:white:";
// 账密安全策略 - 黑名单 /** 账密安全策略 - 黑名单 */
String IPV4_LOCK_BLACK = "lock_ipv4:black:"; String IPV4_LOCK_BLACK = "lock_ipv4:black:";
// 账密安全策略 - 锁机制自定义参数 - 锁定分钟数 /** 账密安全策略 - 锁机制自定义参数 - 锁定分钟数 */
String IPV4_LOCK_MINUTES_REDIS = "lock_ipv4:minutes:"; String IPV4_LOCK_MINUTES_REDIS = "lock_ipv4:minutes:";
// 账密安全策略 - 锁机制自定义参数 - 锁开关阈值 /** 账密安全策略 - 锁机制自定义参数 - 锁开关阈值 */
String IPV4_LOCK_ON_COUNTS_REDIS = "lock_ipv4:on_counts:"; String IPV4_LOCK_ON_COUNTS_REDIS = "lock_ipv4:on_counts:";
// 账密安全策略 - 锁机制 - IPV4锁 /** 账密安全策略 - 锁机制 - IPV4锁 */
String IPV4_LOCK = "lock_ipv4:"; String IPV4_LOCK = "lock_ipv4:";
// 账密不匹配错误 - 锁机制默认参数 - 锁定分钟数 /** 账密不匹配错误 - 锁机制默认参数 - 锁定分钟数 */
Long IPV4_FAILED_LOCK_MINUTES = 3 * 60L; Long IPV4_FAILED_LOCK_MINUTES = 3 * 60L;
// 账密不匹配错误 - 锁机制默认参数 - 计数周期 /** 账密不匹配错误 - 锁机制默认参数 - 计数周期 */
Long IPV4_FAILED_COUNT_MINUTES = 1L; Long IPV4_FAILED_COUNT_MINUTES = 1L;
// 账密不匹配错误 - 锁机制默认参数 - 锁开关阈值 /** 账密不匹配错误 - 锁机制默认参数 - 锁开关阈值 */
Long IPV4_LOCK_ON_FAILED_COUNTS = 60L; Long IPV4_LOCK_ON_FAILED_COUNTS = 60L;
// 账密匹配成功 - 锁机制默认参数 - 锁定分钟数 /** 账密匹配成功 - 锁机制默认参数 - 锁定分钟数 */
Long IPV4_SUCCESS_LOCK_MINUTES = 30L; Long IPV4_SUCCESS_LOCK_MINUTES = 30L;
// 账密匹配成功 - 锁机制默认参数 - 计数周期 /** 账密匹配成功 - 锁机制默认参数 - 计数周期 */
Long IPV4_SUCCESS_COUNT_MINUTES = 1 * 60L; Long IPV4_SUCCESS_COUNT_MINUTES = 1 * 60L;
// 账密匹配成功 - 锁机制默认参数 - 锁开关阈值 /** 账密匹配成功 - 锁机制默认参数 - 锁开关阈值 */
Long IPV4_LOCK_ON_SUCCESS_COUNTS = 40L; Long IPV4_LOCK_ON_SUCCESS_COUNTS = 40L;
// 危险期 - 起始时间(Hour) /** 危险期 - 起始时间(Hour) */
int DANGEROUS_TIME_START = 22; int DANGEROUS_TIME_START = 22;
// 危险期 - 结束时间(Hour) /** 危险期 - 结束时间(Hour) */
int DANGEROUS_TIME_END = 6; int DANGEROUS_TIME_END = 6;
// 安全策略参数设置 - 秘钥 - 口令 /** 安全策略参数设置 - 秘钥 - 口令 */
String CLEAR_LOCK_FOR_IPV4 = "x-clear-lock-11241842-y"; String CLEAR_LOCK_FOR_IPV4 = "x-clear-lock-11241842-y";
// 安全策略参数设置 - 私钥 /** 安全策略参数设置 - 私钥 */
String CLEAR_LOCK_FOR_IPV4_KEY = "lhp.family.dwy.sjs.yym.cxy.cpg"; String CLEAR_LOCK_FOR_IPV4_KEY = "lhp.family.dwy.sjs.yym.cxy.cpg";
// -- End -- IPV4安全策略常量组 // -- End -- IPV4安全策略常量组
/** /**
......
...@@ -232,34 +232,39 @@ public class SmsController implements IBaseController { ...@@ -232,34 +232,39 @@ public class SmsController implements IBaseController {
if (!ValidationUtil.validatePhoneNo(phoneNo)) { if (!ValidationUtil.validatePhoneNo(phoneNo)) {
return JsonResult.buildErrorStateResult("手机号格式有误", null); return JsonResult.buildErrorStateResult("手机号格式有误", null);
} }
String verificationPhoneCountKey = Constants.REDIS_SMS_CODE_COUNT + phoneNo;
Long getPhoneVerificationCount = redisTemplate.opsForHash().increment(verificationPhoneCountKey, Constants.REDIS_SMS_CODE_COUNT, 1);
redisTemplate.expire(verificationPhoneCountKey, DateUtils.getSeconds(), TimeUnit.SECONDS);
String clientIp = getIp(); String clientIp = getIp();
LOGGER.info("请求短信新版本接口:phoneNo:{},deviceId:{},IP:{}",phoneNo,deviceId,clientIp);
// 手机号计数器
Long getPhoneVerificationCount = redisTemplate.opsForHash().increment(Constants.REDIS_SMS_CODE_COUNT, phoneNo, 1);
redisTemplate.expire(Constants.REDIS_SMS_CODE_COUNT, DateUtils.getSeconds(), TimeUnit.SECONDS);
// 设备号计数器
Long getDeviceVerificationCount = 0L;
if (StringUtils.isNotBlank(deviceId)) {
getDeviceVerificationCount = redisTemplate.opsForHash().increment(Constants.REDIS_SMS_DEVICE_COUNT, deviceId, 1);
redisTemplate.expire(Constants.REDIS_SMS_DEVICE_COUNT, DateUtils.getSeconds(), TimeUnit.SECONDS);
}
// IP计数器
Long getIPVerificationCount = 0L;
if (StringUtils.isNotBlank(clientIp)) {
getIPVerificationCount = redisTemplate.opsForHash().increment(Constants.REDIS_SMS_IP_COUNT, clientIp, 1);
redisTemplate.expire(Constants.REDIS_SMS_IP_COUNT, DateUtils.getSeconds(), TimeUnit.SECONDS);
}
// 手机号上限检查
if (getPhoneVerificationCount > PHONE_MAX_PER_DAY) { if (getPhoneVerificationCount > PHONE_MAX_PER_DAY) {
LOGGER.info("您手机号已经达到获取今天短信验证码上限:phoneNo:{},deviceId:{},ip:{}",phoneNo,deviceId,clientIp); LOGGER.info("您手机号已经达到获取今天短信验证码上限:phoneNo:{},count:{}", phoneNo, getPhoneVerificationCount);
return JsonResult.buildErrorStateResult("今天已获取20次短信验证码,请使用语音验证码或明天再试", null); return JsonResult.buildErrorStateResult("今天已获取20次短信验证码,请使用语音验证码或明天再试", null);
} }
// Todo - 运维解决真实IP获取问题后,打开这段代码,实现按IP限制短信验证码获取量 // 设备号上限检查
// Todo - 另:当前的计数器计数方式为乐观累加,而且还是提前计数,会导致边界值问题,即临界次数会提前一次记满,并且在后续请求到达时计数器会继续计数
/*
if (!StringUtils.isEmpty(clientIp)) {
String verificationIPCountKey = Constants.REDIS_SMS_IP_COUNT+clientIp;
Long getIPVerificationCount = redisTemplate.opsForHash().increment(verificationIPCountKey, Constants.REDIS_SMS_IP_COUNT, 1);
if (getIPVerificationCount > IP_MAX_PER_DAY) {
return JsonResult.buildErrorStateResult("您当前ip已经达到获取今天验证码上限", null);
}
}*/
LOGGER.info("请求短信新版本接口:phoneNo:{},deviceId:{},IP:{}",phoneNo,deviceId,clientIp);
if (!StringUtils.isEmpty(deviceId)) {
String verificationDeviceCountKey = Constants.REDIS_SMS_DEVICE_COUNT + deviceId;
Long getDeviceVerificationCount = redisTemplate.opsForHash().increment(verificationDeviceCountKey, Constants.REDIS_SMS_DEVICE_COUNT, 1);
redisTemplate.expire(verificationDeviceCountKey, DateUtils.getSeconds(), TimeUnit.SECONDS);
if (getDeviceVerificationCount > DEVICE_MAX_PER_DAY) { if (getDeviceVerificationCount > DEVICE_MAX_PER_DAY) {
LOGGER.info("您设备已经达到获取今天短信验证码上限:phoneNo:{},deviceId:{},ip:{}",phoneNo,verificationDeviceCountKey,clientIp); LOGGER.info("您设备已经达到获取今天验证码上限:deviceId:{},count:{}", deviceId, getDeviceVerificationCount);
return JsonResult.buildErrorStateResult("您设备已经达到获取今天短信验证码上限", null); return JsonResult.buildErrorStateResult("您设备已经达到获取今天验证码上限", null);
}
} }
// Todo - 运维解决真实IP获取问题后,打开这段代码,实现按IP限制短信验证码获取量
// IP上限检查
/*if (getIPVerificationCount > IP_MAX_PER_DAY) {
LOGGER.info("您当前ip已经达到获取今天短信验证码上限:ip:{},count:{}", clientIp, getIPVerificationCount);
return JsonResult.buildErrorStateResult("您当前ip已经达到获取今天短信验证码上限", null);
}*/
String key = Constants.REDIS_PREFIX_VERIFICATION_CODE + phoneNo; String key = Constants.REDIS_PREFIX_VERIFICATION_CODE + phoneNo;
long expire = redisTemplate.getExpire(key, TimeUnit.MINUTES); long expire = redisTemplate.getExpire(key, TimeUnit.MINUTES);
...@@ -275,7 +280,8 @@ public class SmsController implements IBaseController { ...@@ -275,7 +280,8 @@ public class SmsController implements IBaseController {
try { try {
smsService.getSmsSender().sendMsg(message); smsService.getSmsSender().sendMsg(message);
redisTemplate.opsForValue().set(key, uniqueId + ":" + randomCode, EXPIRE_MINUTES, TimeUnit.MINUTES); redisTemplate.opsForValue().set(key, uniqueId + ":" + randomCode, EXPIRE_MINUTES, TimeUnit.MINUTES);
deleteRetSendCode(phoneNo);//删除用户重置密码,多次错误逻辑 //删除用户重置密码,多次错误逻辑
deleteRetSendCode(phoneNo);
if(isApp && needImageVlidate(clientIp,deviceId,phoneNo)){ if(isApp && needImageVlidate(clientIp,deviceId,phoneNo)){
return JsonResult.buildSuccessResult("发送成功", uniqueId,0003L); return JsonResult.buildSuccessResult("发送成功", uniqueId,0003L);
} }
...@@ -291,37 +297,49 @@ public class SmsController implements IBaseController { ...@@ -291,37 +297,49 @@ public class SmsController implements IBaseController {
* 新版本语音验证码 * 新版本语音验证码
*/ */
private JsonResult sendVerificationCode2VoiceNew(String phoneNo, String usage, String deviceId) { private JsonResult sendVerificationCode2VoiceNew(String phoneNo, String usage, String deviceId) {
if (!ValidationUtil.validatePhoneNo(phoneNo)) {
String verificationCountKey = Constants.REDIS_VOICE_CODE_COUNT + phoneNo; return JsonResult.buildErrorStateResult("手机号格式有误", null);
Long getVerificationCount = redisTemplate.opsForHash().increment(verificationCountKey, usage.toString(), 1); }
redisTemplate.expire(verificationCountKey, DateUtils.getSeconds(), TimeUnit.SECONDS); if (StringUtils.isBlank(usage)) {
if (getVerificationCount > PHONE_VOICE_MAX_PER_DAY) { return JsonResult.buildErrorStateResult("usage参数无效", null);
return JsonResult.buildErrorStateResult("今天已获取5次语音验证码,请使用短信验证码或明天再试", null);
} }
String clientIp = getIp(); String clientIp = getIp();
// Todo - 运维解决真实IP获取问题后,打开这段代码,实现按IP限制短信验证码获取量 LOGGER.info("请求短信新版本接口:phoneNo:{},deviceId:{},usage:{},IP:{}",phoneNo,deviceId,usage,clientIp);
// Todo - 另:当前的计数器计数方式为乐观累加,而且还是提前计数,会导致边界值问题,即临界次数会提前一次记满,并且在后续请求到达时计数器会继续计数 // 手机号计数器
/* if (!StringUtils.isEmpty(clientIp)) { String verificationCountKey = Constants.REDIS_VOICE_CODE_COUNT + usage;
Long getPhoneVerificationCount = redisTemplate.opsForHash().increment(verificationCountKey, phoneNo, 1);
redisTemplate.expire(verificationCountKey, DateUtils.getSeconds(), TimeUnit.SECONDS);
// 设备号计数器
Long getDeviceVerificationCount = 0L;
if (StringUtils.isNotBlank(deviceId)) {
String verificationDeviceCountKey = Constants.REDIS_VOICE_DEVICE_COUNT + deviceId;
getDeviceVerificationCount = redisTemplate.opsForHash().increment(Constants.REDIS_VOICE_DEVICE_COUNT, verificationDeviceCountKey, 1);
redisTemplate.expire(Constants.REDIS_VOICE_DEVICE_COUNT, DateUtils.getSeconds(), TimeUnit.SECONDS);
}
// IP计数器
Long getIPVerificationCount = 0L;
if (StringUtils.isNotBlank(clientIp)) {
String verificationIPCountKey = Constants.REDIS_VOICE_IP_COUNT+clientIp; String verificationIPCountKey = Constants.REDIS_VOICE_IP_COUNT+clientIp;
Long getIPVerificationCount = redisTemplate.opsForHash().increment(verificationIPCountKey, Constants.REDIS_VOICE_IP_COUNT, 1); getIPVerificationCount = redisTemplate.opsForHash().increment(Constants.REDIS_VOICE_IP_COUNT, verificationIPCountKey, 1);
if (getIPVerificationCount > IP_MAX_PER_DAY) { redisTemplate.expire(Constants.REDIS_VOICE_IP_COUNT, DateUtils.getSeconds(), TimeUnit.SECONDS);
return JsonResult.buildErrorStateResult("您当前ip已经达到获取今天语音验证码上限", null);
} }
}*/ // 手机号上限检查
if (getPhoneVerificationCount > PHONE_VOICE_MAX_PER_DAY) {
if (!StringUtils.isEmpty(deviceId)) { LOGGER.info("您手机号已经达到获取今天语音验证码,请使用短信验证码或明天再试:phoneNo:{},count:{}", phoneNo, getPhoneVerificationCount);
String verificationDeviceCountKey = Constants.REDIS_VOICE_DEVICE_COUNT + deviceId; return JsonResult.buildErrorStateResult("今天已获取5次语音验证码,请使用短信验证码或明天再试", null);
Long getDeviceVerificationCount = redisTemplate.opsForHash().increment(verificationDeviceCountKey, Constants.REDIS_VOICE_DEVICE_COUNT, 1); }
redisTemplate.expire(verificationDeviceCountKey, DateUtils.getSeconds(), TimeUnit.SECONDS); // 设备号上限检查
if (getDeviceVerificationCount > DEVICE_MAX_PER_DAY) { if (getDeviceVerificationCount > DEVICE_MAX_PER_DAY) {
LOGGER.info("您设备已经达到获取今天语音验证码上限:deviceId:{},count:{}", deviceId, getDeviceVerificationCount);
return JsonResult.buildErrorStateResult("您设备已经达到获取今天语音验证码上限", null); return JsonResult.buildErrorStateResult("您设备已经达到获取今天语音验证码上限", null);
} }
} // Todo - 运维解决真实IP获取问题后,打开这段代码,实现按IP限制短信验证码获取量
// IP上限检查
/*if (getIPVerificationCount > IP_MAX_PER_DAY) {
LOGGER.info("您当前ip已经达到获取今天短信验证码上限:ip:{},count:{}", clientIp, getIPVerificationCount);
return JsonResult.buildErrorStateResult("您当前ip已经达到获取今天语音验证码上限", null);
}*/
if (!ValidationUtil.validatePhoneNo(phoneNo)) {
return JsonResult.buildErrorStateResult("手机号格式有误", null);
}
String key = Constants.REDIS_PREFIX_VERIFICATION_CODE + phoneNo; String key = Constants.REDIS_PREFIX_VERIFICATION_CODE + phoneNo;
long expire = redisTemplate.getExpire(key, TimeUnit.MINUTES); long expire = redisTemplate.getExpire(key, TimeUnit.MINUTES);
if (expire >= EXPIRE_MINUTES - 1) { if (expire >= EXPIRE_MINUTES - 1) {
......
...@@ -553,9 +553,9 @@ public class UserController implements IBaseController { ...@@ -553,9 +553,9 @@ public class UserController implements IBaseController {
countErrorByIpv4(); countErrorByIpv4();
return null; return null;
} }
LOGGER.info("用户正在登录... [{}]", bufStr);
String phoneNo = credentialArr[0]; String phoneNo = credentialArr[0];
String pass = credentialArr[1]; String pass = credentialArr[1];
LOGGER.info("用户正在登录... [{}]", phoneNo);
User user = userService.findByPhoneWithCache(phoneNo); User user = userService.findByPhoneWithCache(phoneNo);
if (user == null || !user.getEnable()) { if (user == null || !user.getEnable()) {
// 向该phoneNo添加错误计数器 // 向该phoneNo添加错误计数器
...@@ -615,7 +615,7 @@ public class UserController implements IBaseController { ...@@ -615,7 +615,7 @@ public class UserController implements IBaseController {
stringRedisTemplate.opsForValue().set(ipv4Key, String.valueOf(0), Constants.IPV4_FAILED_COUNT_MINUTES, TimeUnit.MINUTES); stringRedisTemplate.opsForValue().set(ipv4Key, String.valueOf(0), Constants.IPV4_FAILED_COUNT_MINUTES, TimeUnit.MINUTES);
} }
Long count = stringRedisTemplate.opsForValue().increment(ipv4Key, 1L); Long count = stringRedisTemplate.opsForValue().increment(ipv4Key, 1L);
LOGGER.info("Lock_ipv4: count ip access: ip={}, count={}", ipv4, count); LOGGER.info("Lock_ipv4: count error ip access: ip={}, count={}", ipv4, count);
lockErrorIpv4(ipv4, count); lockErrorIpv4(ipv4, count);
} }
} }
...@@ -643,7 +643,7 @@ public class UserController implements IBaseController { ...@@ -643,7 +643,7 @@ public class UserController implements IBaseController {
} }
String lockIpv4Key = getLockIpv4Key(ip); String lockIpv4Key = getLockIpv4Key(ip);
stringRedisTemplate.opsForValue().set(lockIpv4Key, Boolean.TRUE.toString(), minutes, TimeUnit.MINUTES); stringRedisTemplate.opsForValue().set(lockIpv4Key, Boolean.TRUE.toString(), minutes, TimeUnit.MINUTES);
LOGGER.info("Lock_ipv4: locked ip access:{}, error overstep {} times in {} minutes, do lock {} minutes", ip, counts, Constants.IPV4_FAILED_COUNT_MINUTES, minutes); LOGGER.info("Lock_ipv4: locked error ip access:{}, error overstep {} times in {} minutes, do lock {} minutes", ip, counts, Constants.IPV4_FAILED_COUNT_MINUTES, minutes);
} }
/** /**
...@@ -662,7 +662,7 @@ public class UserController implements IBaseController { ...@@ -662,7 +662,7 @@ public class UserController implements IBaseController {
stringRedisTemplate.opsForValue().set(ipv4Key, String.valueOf(0), Constants.IPV4_SUCCESS_COUNT_MINUTES, TimeUnit.MINUTES); stringRedisTemplate.opsForValue().set(ipv4Key, String.valueOf(0), Constants.IPV4_SUCCESS_COUNT_MINUTES, TimeUnit.MINUTES);
} }
Long count = stringRedisTemplate.opsForValue().increment(ipv4Key, 1L); Long count = stringRedisTemplate.opsForValue().increment(ipv4Key, 1L);
LOGGER.info("Lock_ipv4: count ip access: ip={}, count={}", ipv4, count); LOGGER.info("Lock_ipv4: count success ip access: ip={}, count={}", ipv4, count);
lockSuccessIpv4(ipv4, count); lockSuccessIpv4(ipv4, count);
} }
} }
...@@ -680,7 +680,7 @@ public class UserController implements IBaseController { ...@@ -680,7 +680,7 @@ public class UserController implements IBaseController {
// 锁定时长 // 锁定时长
String lockIpv4Key = getLockIpv4Key(ip); String lockIpv4Key = getLockIpv4Key(ip);
stringRedisTemplate.opsForValue().set(lockIpv4Key, Boolean.TRUE.toString(), Constants.IPV4_SUCCESS_LOCK_MINUTES, TimeUnit.MINUTES); stringRedisTemplate.opsForValue().set(lockIpv4Key, Boolean.TRUE.toString(), Constants.IPV4_SUCCESS_LOCK_MINUTES, TimeUnit.MINUTES);
LOGGER.info("Lock_ipv4: locked ip access:{}, success overstep {} times in {} minutes, do lock {} minutes", ip, Constants.IPV4_LOCK_ON_SUCCESS_COUNTS, Constants.IPV4_SUCCESS_COUNT_MINUTES, Constants.IPV4_SUCCESS_LOCK_MINUTES); LOGGER.info("Lock_ipv4: locked success ip access:{}, success overstep {} times in {} minutes, do lock {} minutes", ip, Constants.IPV4_LOCK_ON_SUCCESS_COUNTS, Constants.IPV4_SUCCESS_COUNT_MINUTES, Constants.IPV4_SUCCESS_LOCK_MINUTES);
} }
private final static String getErrorIpKey(String ipv4){ private final static String getErrorIpKey(String ipv4){
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment