package com.cyksj.service.user.impl; import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONObject; import com.cyksj.common.exception.BusinessRuntimeException; import com.cyksj.common.util.StringUtil; import com.cyksj.redis.RedisService; import com.cyksj.service.user.BadIntentionOpService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; @Service @RequiredArgsConstructor @Slf4j public class BadIntentionOpServiceImpl implements BadIntentionOpService { @Value("${smsVerify.apiKey}") String apiKey; private final RedisService redisService; private static final int PHONE_CODE_GET_NUM_DAY_LIMIT = 30; private static final int PHONE_CODE_GET_NUM_DAY_MAX_BLACK = 50; private static final int PHONE_LOGIN_CODE_RETRY = 10; private static final String VERIFY_URL = "https://captcha.luosimao.com/api/site_verify"; @Override public void checkHandleBadUserOp(String phone, String verifyCode) { if ("13662979985".equals(phone)) { throw BusinessRuntimeException.getInstance("异常手机号"); } String dayKey = RedisService.key.PHONE_CODE_USER_NUM_KEY_DAY.getName() + phone; if (redisService.hasKey(RedisService.key.PHONE_CODE_BALCK_KEY.getName() + phone)) { throw BusinessRuntimeException.getInstance("异常手机号"); } if (redisService.hasKey(dayKey)) { Long incr = redisService.incr(dayKey, 1l); if (incr.intValue() >= PHONE_CODE_GET_NUM_DAY_MAX_BLACK) { log.error("近一天内手机号:{}获取验证码超过50次,移入黑名单", phone); redisService.set(RedisService.key.PHONE_CODE_BALCK_KEY.getName() + phone, phone); } if (incr.intValue() > PHONE_CODE_GET_NUM_DAY_LIMIT) { log.error("手机号:{}频繁获取短信验证码", phone); throw BusinessRuntimeException.getInstance("请勿频繁获取短信验证码"); } if (StringUtils.isBlank(verifyCode)) { throw BusinessRuntimeException.getInstance("人机校验不通过"); }else { JSONObject parmas = new JSONObject(); parmas.putOpt("api_key", apiKey); parmas.putOpt("response", verifyCode); String post = HttpUtil.post(VERIFY_URL, parmas.toString()); JSONObject res = new JSONObject(post); if (!res.getStr("res").equals("success")) { log.error("手机号:{}验证码校验不通过 res:{}", phone, res); throw BusinessRuntimeException.getInstance("人机校验不通过"); } } return; } redisService.set(dayKey, 1, RedisService.key.PHONE_CODE_USER_NUM_KEY_DAY.getTimeout()); } @Override public void isBadOpLoginPhone(HttpServletRequest request, String phone) { String ip = StringUtil.getInternalAddressByIP(ServletUtil.getClientIP(request)); String blackIpKey = RedisService.key.BALCK_USER_IP_KEY + ip; if (redisService.hasKey(blackIpKey)) { throw BusinessRuntimeException.getInstance("检测到您操作异常,请联系客服"); } String RetryTimeKey = RedisService.key.PHONE_CODE_RETRY_TIME_KEY.getName() + phone; if (redisService.hasKey(RetryTimeKey)) { int i = Integer.parseInt(redisService.get(RetryTimeKey).toString()); if (i >= PHONE_LOGIN_CODE_RETRY) { //锁住他的ip redisService.setNx(blackIpKey, ip, RedisService.key.BALCK_USER_IP_KEY.getTimeout()); throw BusinessRuntimeException.getInstance("检测到您操作异常,请联系客服"); } else { redisService.incr(RetryTimeKey, 1l); } } else { redisService.setNx(RetryTimeKey, 1, RedisService.key.PHONE_CODE_RETRY_TIME_KEY.getTimeout()); } } }