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

Merge branch 'master' into feature/20171030

# Conflicts:
#	src/main/java/cn/quantgroup/xyqb/Constants.java
#	src/main/java/cn/quantgroup/xyqb/controller/internal/user/UserController.java
#	src/main/java/cn/quantgroup/xyqb/filter/RequestFilter.java
parents 06a04a63 f5a3d56f
...@@ -3,8 +3,6 @@ package cn.quantgroup.xyqb.aspect.captcha; ...@@ -3,8 +3,6 @@ package cn.quantgroup.xyqb.aspect.captcha;
import cn.quantgroup.xyqb.Constants; import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.model.JsonResult; import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.util.ValidationUtil;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Around;
...@@ -20,7 +18,7 @@ import org.springframework.web.context.request.RequestContextHolder; ...@@ -20,7 +18,7 @@ import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.*; import java.util.Objects;
/** /**
* 密码错误限次的校验 * 密码错误限次的校验
...@@ -61,6 +59,9 @@ public class PasswordErrorFiniteValidateAdvisor { ...@@ -61,6 +59,9 @@ public class PasswordErrorFiniteValidateAdvisor {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 客户端IP // 客户端IP
String clientIp = getIp(request); String clientIp = getIp(request);
if (StringUtils.startsWith(clientIp, "139.198.")){
return pjp.proceed();
}
String lockIpv4Key = getLockIpv4Key(clientIp); String lockIpv4Key = getLockIpv4Key(clientIp);
String lock = redisTemplate.opsForValue().get(lockIpv4Key); String lock = redisTemplate.opsForValue().get(lockIpv4Key);
if (Objects.equals(Boolean.TRUE.toString(), lock)){ if (Objects.equals(Boolean.TRUE.toString(), lock)){
......
package cn.quantgroup.xyqb.controller.internal.user; package cn.quantgroup.xyqb.controller.internal.user;
import cn.quantgroup.xyqb.Constants; import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.aspect.captcha.CaptchaFineteValidator;
import cn.quantgroup.xyqb.aspect.captcha.PasswordFineteValidator; import cn.quantgroup.xyqb.aspect.captcha.PasswordFineteValidator;
import cn.quantgroup.xyqb.aspect.logcaller.LogHttpCaller; import cn.quantgroup.xyqb.aspect.logcaller.LogHttpCaller;
import cn.quantgroup.xyqb.controller.IBaseController; import cn.quantgroup.xyqb.controller.IBaseController;
...@@ -9,9 +8,7 @@ import cn.quantgroup.xyqb.entity.Merchant; ...@@ -9,9 +8,7 @@ import cn.quantgroup.xyqb.entity.Merchant;
import cn.quantgroup.xyqb.entity.User; import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.entity.UserDetail; import cn.quantgroup.xyqb.entity.UserDetail;
import cn.quantgroup.xyqb.entity.WechatUserInfo; import cn.quantgroup.xyqb.entity.WechatUserInfo;
import cn.quantgroup.xyqb.exception.PasswordErrorLimitException;
import cn.quantgroup.xyqb.exception.UserNotExistException; import cn.quantgroup.xyqb.exception.UserNotExistException;
import cn.quantgroup.xyqb.exception.VerificationCodeErrorException;
import cn.quantgroup.xyqb.model.JsonResult; import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.UserModel; import cn.quantgroup.xyqb.model.UserModel;
import cn.quantgroup.xyqb.model.UserRegisterMqMessage; import cn.quantgroup.xyqb.model.UserRegisterMqMessage;
...@@ -22,10 +19,8 @@ import cn.quantgroup.xyqb.service.sms.ISmsService; ...@@ -22,10 +19,8 @@ import cn.quantgroup.xyqb.service.sms.ISmsService;
import cn.quantgroup.xyqb.service.user.IUserDetailService; import cn.quantgroup.xyqb.service.user.IUserDetailService;
import cn.quantgroup.xyqb.service.user.IUserService; import cn.quantgroup.xyqb.service.user.IUserService;
import cn.quantgroup.xyqb.service.wechat.IWechatService; import cn.quantgroup.xyqb.service.wechat.IWechatService;
import cn.quantgroup.xyqb.util.DateUtils; import cn.quantgroup.xyqb.util.*;
import cn.quantgroup.xyqb.util.MqUtils; import cn.quantgroup.xyqb.util.encrypt.MD5Util;
import cn.quantgroup.xyqb.util.PasswordUtil;
import cn.quantgroup.xyqb.util.ValidationUtil;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -40,14 +35,10 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -40,14 +35,10 @@ import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.HashMap; import java.util.*;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
* Http服务接口:用户注册、登录、重置密码
* Created by FrankChow on 15/7/5. * Created by FrankChow on 15/7/5.
*/ */
@RestController @RestController
...@@ -56,7 +47,6 @@ public class UserController implements IBaseController { ...@@ -56,7 +47,6 @@ public class UserController implements IBaseController {
private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class); private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class);
private final String pwdSalt = "_lkb"; private final String pwdSalt = "_lkb";
@Autowired @Autowired
...@@ -79,77 +69,65 @@ public class UserController implements IBaseController { ...@@ -79,77 +69,65 @@ public class UserController implements IBaseController {
@Autowired @Autowired
private IWechatService wechatService; private IWechatService wechatService;
private static final char[] PWD_BASE = { private static final char[] PWD_BASE = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};
/** @RequestMapping("/test")
* 登录(账号 + 密码) public JsonResult test() {
* 密码错误达到限定次数时执行图形验证码校验 return JsonResult.buildSuccessResult("", getCurrentUserFromRedis());
* 图形验证码累计错误达到限定次数时须重新获取
*
* @param channelId
* @param appChannel
* @param createdFrom
* @param userId
* @param key
* @param request
* @param openId
* @param dimension
* @return
*/
@CaptchaFineteValidator
@RequestMapping("/loginV1")
public JsonResult loginV1(
@RequestParam(required = false, defaultValue = "1") Long channelId, String appChannel,
@RequestParam(required = false, defaultValue = "1") Long createdFrom,
@RequestParam(required = false, defaultValue = "") String userId,
@RequestParam(required = false,defaultValue = "xyqb") String key,
HttpServletRequest request, String openId,
@RequestParam(required = false) String dimension) {
LOGGER.info("loginV1 -> channelId:{},appChennel:{},createdFrom:{},userId:{},key:{},openId:{},dimension:{}",channelId, appChannel, createdFrom, userId, key, openId, dimension);
return login(channelId, appChannel, createdFrom, userId, key, request, openId, dimension);
} }
/** /**
* 快速登录(手机号 + 短信验证码),H5专用入口 * 解锁特定IP
* 短信验证码错误达到限定次数时执行图形验证码校验 * @param ip - 目标IP
* 图形验证码累计错误达到限定次数时须重新获取 * @param act - 操作标记,true-lock,false-unlock
* * @param key - 密令
* @param channelId
* @param appChannel
* @param createdFrom
* @param key
* @param btRegisterChannelId
* @param dimension
* @param request * @param request
* @return * @return
*/ */
// Todo @OneTimeTokenValidator @RequestMapping("/lock_ipv4")
@RequestMapping("/login/fastV1") public JsonResult clearOrLockIpv4(@RequestParam(required = true)String ip,
public JsonResult loginFastV1( @RequestParam(required = false)String act,
@RequestParam(required = false, defaultValue = "1") Long channelId, String appChannel, @RequestParam(required = true)String key,
@RequestParam(required = false, defaultValue = "1") Long createdFrom, HttpServletRequest request) {
@RequestParam(required = false,defaultValue = "xyqb") String key, if(!ValidationUtil.validateIpv4(ip) || StringUtils.isBlank(act) || StringUtils.isBlank(key)){
@RequestParam(required = false)Long btRegisterChannelId, LOGGER.info("Fail to clear_or_lock ip:{}", ip);
@RequestParam(required = false) String dimension ,HttpServletRequest request) { return JsonResult.buildErrorStateResult("Are you a robot monkey?(^_^)",null);
LOGGER.info("login/fastV1 -> channelId:{},appChennel:{},createdFrom:{},key:{},btRegisterChannelId:{},dimension:{}",channelId, appChannel, createdFrom, key, btRegisterChannelId, dimension); }
return loginFast(channelId, appChannel, createdFrom, key, btRegisterChannelId, dimension, request); // 操作标记
boolean lock = Objects.equals(Boolean.TRUE.toString(), act);
String header_key = request.getHeader(Constants.IPV4_LOCK.replace(":", ""));
if(Objects.equals(Constants.CLEAR_LOCK_FOR_IPV4, header_key)){
return JsonResult.buildErrorStateResult("Are you a robot monkey?(^_^)", ValidationUtil.getMd5Key(lock));
}
boolean valid = ValidationUtil.isValid(key, lock);
if(!valid){
Calendar now = Calendar.getInstance();
int hour = now.get(Calendar.HOUR_OF_DAY);
valid = Objects.equals(Constants.CLEAR_LOCK_FOR_IPV4_KEY+hour, key);
}
if(valid){
String lockIpv4Key = getLockIpv4Key(ip);
if(lock){
stringRedisTemplate.opsForValue().set(lockIpv4Key, Boolean.TRUE.toString(), Constants.IPV4_LOCK_MINUTES, TimeUnit.MINUTES);
LOGGER.info("Locked ip access:{}, error overstep {} times in {} minutes, do lock {} minutes", ip, Constants.IPV4_LOCK_ON_COUNTS, Constants.IPV4_COUNT_MINUTES, Constants.IPV4_LOCK_MINUTES);
}else{
stringRedisTemplate.delete(lockIpv4Key);
LOGGER.info("Clear_or_lock ip Success:{}", ip);
}
return JsonResult.buildSuccessResult("Success",null);
}
LOGGER.info("Fail to clear_or_lock ip:{}", ip);
return JsonResult.buildErrorStateResult("Are you a robot monkey?(^_^)",null);
} }
@LogHttpCaller
@PasswordFineteValidator @PasswordFineteValidator
@RequestMapping("/login") @RequestMapping("/login")
public JsonResult login( public JsonResult login(
@RequestParam(required = false, defaultValue = "1") Long channelId, String appChannel, @RequestParam(required = false, defaultValue = "1") Long channelId, String appChannel,
@RequestParam(required = false, defaultValue = "1") Long createdFrom, @RequestParam(required = false, defaultValue = "1") Long createdFrom,
@RequestParam(required = false, defaultValue = "") String userId, @RequestParam(required = false, defaultValue = "") String userId, @RequestParam(required = false,defaultValue = "xyqb") String key, HttpServletRequest request, String openId,@RequestParam(required = false) String dimension) {
@RequestParam(required = false,defaultValue = "xyqb") String key,
HttpServletRequest request, String openId,
@RequestParam(required = false) String dimension) {
LOGGER.info("user/login,请求参数channelId:{},appChannel:{},createdFrom:{},userId:{},key:{},openId:{},dimension:{},",channelId,appChannel,createdFrom,userId,key,openId,dimension); LOGGER.info("user/login,请求参数channelId:{},appChannel:{},createdFrom:{},userId:{},key:{},openId:{},dimension:{},",channelId,appChannel,createdFrom,userId,key,openId,dimension);
Merchant merchant = merchantService.findMerchantByName(key); Merchant merchant = merchantService.findMerchantByName(key);
if (merchant == null) { if (merchant == null) {
...@@ -163,20 +141,13 @@ public class UserController implements IBaseController { ...@@ -163,20 +141,13 @@ public class UserController implements IBaseController {
} }
} }
@RequestMapping("/test")
public JsonResult test() {
return JsonResult.buildSuccessResult("", getCurrentUserFromRedis());
}
@RequestMapping("/login/fast") @RequestMapping("/login/fast")
public JsonResult loginFast( public JsonResult loginFast(
@RequestParam(required = false, defaultValue = "1") Long channelId, String appChannel, @RequestParam(required = false, defaultValue = "1") Long channelId, String appChannel,
@RequestParam(required = false, defaultValue = "1") Long createdFrom, @RequestParam(required = false, defaultValue = "1") Long createdFrom, @RequestParam(required = false,defaultValue = "xyqb") String key,@RequestParam(required = false)Long btRegisterChannelId,@RequestParam(required = false) String dimension ,HttpServletRequest request) {
@RequestParam(required = false,defaultValue = "xyqb") String key, Map<String, JsonResult> validMap = getHeaderParam(request);
@RequestParam(required = false)Long btRegisterChannelId,
@RequestParam(required = false) String dimension ,HttpServletRequest request) {
Map<String, JsonResult> validMap = getHeaderParam(request);
LOGGER.info("user/login/fast,请求参数channelId:{},appChannel:{},createdFrom:{},btRegisterChannelId:{},key:{},dimension:{},",channelId,appChannel,createdFrom,btRegisterChannelId,key,dimension); LOGGER.info("user/login/fast,请求参数channelId:{},appChannel:{},createdFrom:{},btRegisterChannelId:{},key:{},dimension:{},",channelId,appChannel,createdFrom,btRegisterChannelId,key,dimension);
if (null != validMap.get("fail")) { if (null != validMap.get("fail")) {
return validMap.get("fail"); return validMap.get("fail");
} }
...@@ -186,9 +157,6 @@ public class UserController implements IBaseController { ...@@ -186,9 +157,6 @@ public class UserController implements IBaseController {
} }
JsonResult successResult = validMap.get("success"); JsonResult successResult = validMap.get("success");
String phoneNo = successResult.getData().toString(); String phoneNo = successResult.getData().toString();
String verificationCode = successResult.getMsg();
// 执行短信验证码检查
smsValidForFastLogin(phoneNo, verificationCode);
User user = userService.findByPhoneWithCache(phoneNo); User user = userService.findByPhoneWithCache(phoneNo);
if (user != null && !user.getEnable()) { if (user != null && !user.getEnable()) {
LOGGER.error("用户不存在,或者已经注销,phoneNo:{}",phoneNo); LOGGER.error("用户不存在,或者已经注销,phoneNo:{}",phoneNo);
...@@ -209,7 +177,7 @@ public class UserController implements IBaseController { ...@@ -209,7 +177,7 @@ public class UserController implements IBaseController {
private User registerFastWhenLogin(String phoneNo, Long channelId, Long registerFrom, String appChannel, Long btRegisterChannelId,String dimension) { private User registerFastWhenLogin(String phoneNo, Long channelId, Long registerFrom, String appChannel, Long btRegisterChannelId,String dimension) {
String password = genRandomPwd(); String password = genRandomPwd();
LOGGER.info("用户快速注册, phoneNo:{}, channelId:{}, registerFrom:{},appChannel:{},btRegisterChannelId", phoneNo, channelId, registerFrom, appChannel,btRegisterChannelId); LOGGER.info("用户快速注册, phoneNo:{}, verificationCode:{}, channelId:{}, registerFrom:{},appChannel:{},btRegisterChannelId", phoneNo, channelId, registerFrom, appChannel,btRegisterChannelId);
if (!ValidationUtil.validatePhoneNo(phoneNo)) { if (!ValidationUtil.validatePhoneNo(phoneNo)) {
LOGGER.info("用户快速注册失败,手机号错误, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo); LOGGER.info("用户快速注册失败,手机号错误, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo);
throw new UserNotExistException("手机号错误"); throw new UserNotExistException("手机号错误");
...@@ -233,16 +201,14 @@ public class UserController implements IBaseController { ...@@ -233,16 +201,14 @@ public class UserController implements IBaseController {
* @return * @return
*/ */
private Map<String, JsonResult> getHeaderParam(HttpServletRequest request) { private Map<String, JsonResult> getHeaderParam(HttpServletRequest request) {
Map<String, JsonResult> result = new HashMap<String, JsonResult>(); Map<String, JsonResult> result = new HashMap<>();
String verificationHeader = "Verification "; String verificationHeader = "Verification ";
String credential = request.getHeader("authorization"); String credential = request.getHeader("authorization");
if (StringUtils.isBlank(credential)) { if (StringUtils.isBlank(credential)) {
result.put("fail", JsonResult.buildErrorStateResult("登录失败", null)); result.put("fail", JsonResult.buildErrorStateResult("登录失败", null));
return result;
} }
if (!credential.startsWith(verificationHeader)) { if (!credential.startsWith(verificationHeader)) {
result.put("fail", JsonResult.buildErrorStateResult("登录失败", null)); result.put("fail", JsonResult.buildErrorStateResult("登录失败", null));
return result;
} }
credential = credential.substring(verificationHeader.length(), credential.length()); credential = credential.substring(verificationHeader.length(), credential.length());
byte[] buf = Base64.decodeBase64(credential); byte[] buf = Base64.decodeBase64(credential);
...@@ -250,18 +216,17 @@ public class UserController implements IBaseController { ...@@ -250,18 +216,17 @@ public class UserController implements IBaseController {
String[] credentialArr = credential.split(":"); String[] credentialArr = credential.split(":");
if (credentialArr.length != 2) { if (credentialArr.length != 2) {
result.put("fail", JsonResult.buildErrorStateResult("登录失败", null)); result.put("fail", JsonResult.buildErrorStateResult("登录失败", null));
return result;
} }
String phoneNo = credentialArr[0]; String phoneNo = credentialArr[0];
String verificationCode = credentialArr[1]; String verificationCode = credentialArr[1];
LOGGER.info("用户快速登录,phoneNo:{} , verificationCode:{}", phoneNo, verificationCode); LOGGER.info("用户快速登录,phoneNo:{} , verificationCode:{}", phoneNo, verificationCode);
if (!ValidationUtil.validatePhoneNo(phoneNo) || StringUtils.isBlank(verificationCode)) { if (!ValidationUtil.validatePhoneNo(phoneNo)) {
result.put("fail", JsonResult.buildErrorStateResult("登录失败", null)); result.put("fail", JsonResult.buildErrorStateResult("登录失败", null));
return result;
} }
// 校验短信密码 // 校验短信密码
validateFastLoginVerificationCode(result, phoneNo, verificationCode); validateFastLoginVerificationCode(result, phoneNo, verificationCode);
result.put("success", JsonResult.buildSuccessResult(verificationCode, phoneNo));
result.put("success", JsonResult.buildSuccessResult("", phoneNo));
return result; return result;
} }
...@@ -276,18 +241,7 @@ public class UserController implements IBaseController { ...@@ -276,18 +241,7 @@ public class UserController implements IBaseController {
return; return;
} }
// 短信密码错误时,给该账号添加计数器 // 短信密码错误时,给该账号添加计数器
countErrorForPhoneNo(result, phoneNo, verificationCode); String passwordErrorCountKey = Constants.REDIS_PASSWORD_ERROR_COUNT + phoneNo;
}
/**
* 短信密码错误时,给该账号添加计数器
* @param result Map
* @param phoneNo 登录手机号
* @param verificationCode 短信密码
*/
private void countErrorForPhoneNo(Map<String, JsonResult> result, String phoneNo, String verificationCode) {
String passwordErrorCountKey = Constants.REDIS_PASSWORD_ERROR_COUNT_FOR_PHONE + phoneNo;
if (!stringRedisTemplate.hasKey(passwordErrorCountKey)) { if (!stringRedisTemplate.hasKey(passwordErrorCountKey)) {
stringRedisTemplate.opsForValue().set(passwordErrorCountKey, String.valueOf(0), Constants.ONE_DAY, TimeUnit.SECONDS); stringRedisTemplate.opsForValue().set(passwordErrorCountKey, String.valueOf(0), Constants.ONE_DAY, TimeUnit.SECONDS);
} }
...@@ -315,7 +269,6 @@ public class UserController implements IBaseController { ...@@ -315,7 +269,6 @@ public class UserController implements IBaseController {
* @param channelId * @param channelId
* @return * @return
*/ */
@LogHttpCaller
@RequestMapping("/register/fast") @RequestMapping("/register/fast")
public JsonResult registerFast(@RequestParam String phoneNo, @RequestParam String verificationCode, @RequestParam(required = false) Long channelId, public JsonResult registerFast(@RequestParam String phoneNo, @RequestParam String verificationCode, @RequestParam(required = false) Long channelId,
@RequestParam(required = false) Long registerFrom, @RequestParam(required = false, defaultValue = "") String appChannel, @RequestParam(required = false) Long registerFrom, @RequestParam(required = false, defaultValue = "") String appChannel,
...@@ -337,22 +290,27 @@ public class UserController implements IBaseController { ...@@ -337,22 +290,27 @@ public class UserController implements IBaseController {
if (null == registerFrom) { if (null == registerFrom) {
registerFrom = 1L; registerFrom = 1L;
} }
smsValidForFastLogin(phoneNo, verificationCode);
if (userService.exist(phoneNo)) { if (userService.exist(phoneNo)) {
LOGGER.info("用户快速注册失败,该手机号已经被注册, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo); LOGGER.info("用户快速注册失败,该手机号已经被注册, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo);
return JsonResult.buildErrorStateResult("该手机号已经被注册", null); return JsonResult.buildErrorStateResult("该手机号已经被注册", null);
} }
if (!smsService.validRegisterOrResetPasswdVerificationCode(phoneNo, verificationCode)) {
LOGGER.info("用户快速注册失败,短信验证码错误, registerFrom:{}, phoneNo:{}, verificationCode:{}", registerFrom, phoneNo, verificationCode);
return JsonResult.buildErrorStateResult("短信验证码错误", null);
}
if (!userService.register(phoneNo, password, registerFrom, getIp(), channelId,btRegisterChannelId,dimension)) { if (!userService.register(phoneNo, password, registerFrom, getIp(), channelId,btRegisterChannelId,dimension)) {
LOGGER.info("用户快速注册失败,请稍后重试, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo); LOGGER.info("用户快速注册失败,请稍后重试, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo);
return JsonResult.buildErrorStateResult("注册失败,请稍后重试", null); return JsonResult.buildErrorStateResult("注册失败,请稍后重试", null);
} }
LOGGER.info("用户快速注册成功, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo); LOGGER.info("用户快速注册成功, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo);
return JsonResult.buildSuccessResult(null, null); return JsonResult.buildSuccessResult(null, null);
} }
/** /**
* 用户注册 * 用户注册
* *
* @param phoneNo * @param phoneNo
* @param password * @param password
...@@ -381,28 +339,34 @@ public class UserController implements IBaseController { ...@@ -381,28 +339,34 @@ public class UserController implements IBaseController {
if (null == registerFrom) { if (null == registerFrom) {
registerFrom = 1L; registerFrom = 1L;
} }
smsValidForRegister(phoneNo, verificationCode);
if (userService.exist(phoneNo)) { if (userService.exist(phoneNo)) {
LOGGER.info("用户注册失败,该手机号已经被注册, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo); LOGGER.info("用户注册失败,该手机号已经被注册, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo);
return JsonResult.buildErrorStateResult("该手机号已经被注册", null); return JsonResult.buildErrorStateResult("该手机号已经被注册", null);
} }
if (!smsService.validRegisterOrResetPasswdVerificationCode(phoneNo, verificationCode)) {
LOGGER.info("用户注册失败,短信验证码错误, registerFrom:{}, phoneNo:{}, verificationCode:{}", registerFrom, phoneNo, verificationCode);
return JsonResult.buildErrorStateResult("短信验证码错误", null);
}
if (!userService.register(phoneNo, password, registerFrom, getIp(), channelId,btRegisterChannelId,dimension)) { if (!userService.register(phoneNo, password, registerFrom, getIp(), channelId,btRegisterChannelId,dimension)) {
LOGGER.info("用户快速注册失败,请稍后重试, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo); LOGGER.info("用户快速注册失败,请稍后重试, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo);
return JsonResult.buildErrorStateResult("注册失败,请稍后重试", null); return JsonResult.buildErrorStateResult("注册失败,请稍后重试", null);
} }
LOGGER.info("用户注册成功, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo); LOGGER.info("用户注册成功, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo);
return JsonResult.buildSuccessResult(null, null); return JsonResult.buildSuccessResult(null, null);
} }
/** /**
* 检查用户是否存在 * 检查用户是否存在
* *
* @param phoneNo 手机号 * @param phoneNo
* @return * @return
*/ */
@RequestMapping("/exist") @RequestMapping("/exist")
public JsonResult exist(@RequestParam String phoneNo) { public JsonResult exist(@RequestParam String phoneNo) {
LOGGER.info("检查用户是否存在, phoneNo:{}", phoneNo); LOGGER.info("检查用户是否存在, phoneNo:{}", phoneNo);
if (userService.exist(phoneNo)) { if (userService.exist(phoneNo)) {
LOGGER.info("该手机号已经注册, phoneNo:{}", phoneNo); LOGGER.info("该手机号已经注册, phoneNo:{}", phoneNo);
return JsonResult.buildErrorStateResult("该手机号已经注册", null); return JsonResult.buildErrorStateResult("该手机号已经注册", null);
...@@ -410,10 +374,11 @@ public class UserController implements IBaseController { ...@@ -410,10 +374,11 @@ public class UserController implements IBaseController {
return JsonResult.buildSuccessResult(null, null); return JsonResult.buildSuccessResult(null, null);
} }
/** /**
* 检查用户是否存在 * 检查用户是否存在
* *
* @param phoneNo 手机号 * @param phoneNo
* @return * @return
*/ */
@RequestMapping("/exist_check") @RequestMapping("/exist_check")
...@@ -430,7 +395,6 @@ public class UserController implements IBaseController { ...@@ -430,7 +395,6 @@ public class UserController implements IBaseController {
* @param verificationCode * @param verificationCode
* @return * @return
*/ */
@LogHttpCaller
@RequestMapping("/reset_password") @RequestMapping("/reset_password")
public JsonResult resetPassword(@RequestParam String phoneNo, public JsonResult resetPassword(@RequestParam String phoneNo,
@RequestParam String password, @RequestParam String password,
...@@ -445,10 +409,13 @@ public class UserController implements IBaseController { ...@@ -445,10 +409,13 @@ public class UserController implements IBaseController {
if (password.length() < 6 || password.length() > 12) { if (password.length() < 6 || password.length() > 12) {
return JsonResult.buildErrorStateResult("密码应为6-12位", null); return JsonResult.buildErrorStateResult("密码应为6-12位", null);
} }
smsValidForRegister(phoneNo, verificationCode); if (!smsService.validRegisterOrResetPasswdVerificationCode(phoneNo, verificationCode)) {
if (!userService.exist(phoneNo)) { if(needRetSendCode(phoneNo)){
LOGGER.info("修改密码失败,该手机号尚未注册, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo); String key = Constants.REDIS_PREFIX_VERIFICATION_CODE + phoneNo;
return JsonResult.buildErrorStateResult("该手机号尚未注册", null); stringRedisTemplate.delete(key);
return JsonResult.buildErrorStateResult("错误次数过多,请重新获取短信验证码", null);
}
return JsonResult.buildErrorStateResult("短信验证码错误", null);
} }
if (!userService.resetPassword(phoneNo, password)) { if (!userService.resetPassword(phoneNo, password)) {
return JsonResult.buildErrorStateResult("修改密码失败", null); return JsonResult.buildErrorStateResult("修改密码失败", null);
...@@ -459,6 +426,23 @@ public class UserController implements IBaseController { ...@@ -459,6 +426,23 @@ public class UserController implements IBaseController {
return JsonResult.buildSuccessResult(null, null); return JsonResult.buildSuccessResult(null, null);
} }
/**
* 是否需要重新发送短信验证码
* @param phoneNo
* @return
*/
private boolean needRetSendCode(@RequestParam String phoneNo) {
boolean needRetSend=false;
String verificationCountKey = Constants.REDIS_VERIFICATION_COUNT+phoneNo;
Long getVerificationCount = stringRedisTemplate.opsForHash().increment(verificationCountKey, Constants.REDIS_VERIFICATION_COUNT, 1);
//已经存在删除操作增加过期时间防止意外
stringRedisTemplate.expire(verificationCountKey, DateUtils.getSeconds(), TimeUnit.SECONDS);
if(getVerificationCount>5){
return needRetSend=true;
}
return needRetSend;
}
/** /**
* 检查token是否已经过期不存在了 * 检查token是否已经过期不存在了
* *
...@@ -519,13 +503,13 @@ public class UserController implements IBaseController { ...@@ -519,13 +503,13 @@ public class UserController implements IBaseController {
if (null == registerFrom) { if (null == registerFrom) {
registerFrom = 1L; registerFrom = 1L;
} }
User newUser = userService.registerAndReturn(phoneNo, password, registerFrom); LOGGER.info("用户快速注册成功, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo);
if(newUser != null && newUser.getId() != null && newUser.getId() > 0){
LOGGER.info("用户快速注册成功, registerFrom:{}, phoneNo:{}", registerFrom, phoneNo); return userService.registerAndReturn(phoneNo, password, registerFrom);
}
return newUser;
} }
private JsonResult loginWithHttpBasic(Long channelId, String appChannel, Long createdFrom, Merchant merchant, HttpServletRequest request, String openId,String dimension) { private JsonResult loginWithHttpBasic(Long channelId, String appChannel, Long createdFrom, Merchant merchant, HttpServletRequest request, String openId,String dimension) {
User user = verificateUserNameAndPassword(request, openId); User user = verificateUserNameAndPassword(request, openId);
if (user == null) { if (user == null) {
...@@ -534,6 +518,7 @@ public class UserController implements IBaseController { ...@@ -534,6 +518,7 @@ public class UserController implements IBaseController {
//增加登陆统计发送 //增加登陆统计发送
UserStatistics statistics=new UserStatistics(user,dimension,1,channelId); UserStatistics statistics=new UserStatistics(user,dimension,1,channelId);
MqUtils.sendLoanVest(statistics); MqUtils.sendLoanVest(statistics);
LOGGER.info("用户登陆成功phonNo:{},当前ip:{},用户登陆信息:{}",user.getPhoneNo(), IPUtil.getRemoteIP(request),statistics);
return new JsonResult(sessionService.createSession(channelId, createdFrom, appChannel, user, merchant)); return new JsonResult(sessionService.createSession(channelId, createdFrom, appChannel, user, merchant));
} }
...@@ -552,26 +537,20 @@ public class UserController implements IBaseController { ...@@ -552,26 +537,20 @@ public class UserController implements IBaseController {
} }
String[] credentialArr = bufStr.split(":"); String[] credentialArr = bufStr.split(":");
if (credentialArr.length != 2) { if (credentialArr.length != 2) {
LOGGER.info("用户登录失败:{}", bufStr);
// 向该ipv4添加错误计数器 // 向该ipv4添加错误计数器
countErrorByIpv4(); countErrorByIpv4();
return null; return null;
} }
LOGGER.info("用户正在登录... [{}]", credentialArr); String userName = credentialArr[0];
String phoneNo = credentialArr[0];
String pass = credentialArr[1]; String pass = credentialArr[1];
User user = userService.findByPhoneWithCache(phoneNo); User user = userService.findByPhoneWithCache(userName);
if (user == null || !user.getEnable()) { if (user == null || !user.getEnable()) {
// 向该phoneNo添加错误计数器
countErrorByPhoneNo(phoneNo);
// 向该ipv4添加错误计数器 // 向该ipv4添加错误计数器
countErrorByIpv4(); countErrorByIpv4();
return null; return null;
} }
//验证密码 //验证密码
if (!validatePassword(pass, user.getPassword())) { if (!validatePassword(pass, user.getPassword())) {
// 向该phoneNo添加错误计数器
countErrorByPhoneNo(phoneNo);
// 向该ipv4添加错误计数器 // 向该ipv4添加错误计数器
countErrorByIpv4(); countErrorByIpv4();
return null; return null;
...@@ -579,34 +558,13 @@ public class UserController implements IBaseController { ...@@ -579,34 +558,13 @@ public class UserController implements IBaseController {
return user; return user;
} }
/**
* 向该phoneNo添加错误计数器
* @param phoneNo
*/
private void countErrorByPhoneNo(String phoneNo) {
// 密码错误时,给该账号添加计数器
String key = Constants.REDIS_PASSWORD_ERROR_COUNT_FOR_PHONE + phoneNo;
if (!stringRedisTemplate.hasKey(key)) {
LOGGER.info("添加错误计数器,key={}", key);
stringRedisTemplate.opsForValue().set(key, String.valueOf(0), DateUtils.getSeconds(), TimeUnit.SECONDS);
}
// 密码错误计数
Long errorCount = stringRedisTemplate.opsForValue().increment(key, 1L);
if (errorCount > Constants.Image_Need_Count) {
throw new PasswordErrorLimitException("用户名或密码不正确");
} else if (Objects.equals(errorCount, Constants.Image_Need_Count)) {
throw new PasswordErrorLimitException("请输入图形验证码");
}
}
/** /**
* 向该ipv4添加错误计数器 * 向该ipv4添加错误计数器
*/ */
private void countErrorByIpv4() { private void countErrorByIpv4() {
// Todo -- 全天候开放监控 // if(!ValidationUtil.isAtDangerousTime()){
/*if(!ValidationUtil.isAtDangerousTime()){ // return;
return; // }
}*/
String ipv4 = getIp(); String ipv4 = getIp();
if (StringUtils.isNotBlank(ipv4) && !ValidationUtil.validateLocalIpv4(ipv4)) { if (StringUtils.isNotBlank(ipv4) && !ValidationUtil.validateLocalIpv4(ipv4)) {
String ipv4Key = getIpKey(getIp()); String ipv4Key = getIpKey(getIp());
...@@ -681,53 +639,4 @@ public class UserController implements IBaseController { ...@@ -681,53 +639,4 @@ public class UserController implements IBaseController {
return JsonResult.buildSuccessResult(null, null); return JsonResult.buildSuccessResult(null, null);
} }
/**
* 注册时校验短信验证码
* @param phoneNo
* @param verificationCode
*/
private void smsValidForRegister(String phoneNo, String verificationCode) {
if (!smsService.validRegisterOrResetPasswdVerificationCode(phoneNo, verificationCode)) {
smsReSendOrNot(phoneNo);
LOGGER.info("用户快速注册,验证码校验失败,phoneNo:{} , verificationCode:{}", phoneNo, verificationCode);
throw new VerificationCodeErrorException("短信验证码错误");
}
}
/**
* 登录时校验短信验证码
* @param phoneNo
* @param verificationCode
*/
private void smsValidForFastLogin(String phoneNo, String verificationCode) {
if (!smsService.validateFastLoginVerificationCode(phoneNo, verificationCode)) {
smsReSendOrNot(phoneNo);
LOGGER.info("用户快速登录,验证码校验失败,phoneNo:{} , verificationCode:{}", phoneNo, verificationCode);
throw new VerificationCodeErrorException("短信验证码错误");
}
}
/**
* 是否需要重新获取短信验证码
* @param phoneNo
*/
private void smsReSendOrNot(String phoneNo) {
if(needRetSendCode(phoneNo)){
String key = Constants.REDIS_PREFIX_VERIFICATION_CODE + phoneNo;
stringRedisTemplate.delete(key);
throw new VerificationCodeErrorException("验证码失效,请重新获取");
}
}
/**
* 是否需要重新发送短信验证码
* @param phoneNo
* @return
*/
private boolean needRetSendCode(String phoneNo) {
String verificationCountKey = Constants.REDIS_VERIFICATION_COUNT + phoneNo;
Long getVerificationCount = stringRedisTemplate.opsForHash().increment(verificationCountKey, Constants.REDIS_VERIFICATION_COUNT, 1);
return (getVerificationCount >= 5);
}
} }
...@@ -27,7 +27,7 @@ public class RequestFilter implements Filter { ...@@ -27,7 +27,7 @@ public class RequestFilter implements Filter {
private static final String[] ALLOWED_PATTERNS = { private static final String[] ALLOWED_PATTERNS = {
"/user_detail/**","/hello/**","/innerapi/**", "/user/exist", "/motan/**", "/user/register", "/user/login", "/user/register/fast", "/user_detail/**","/hello/**","/innerapi/**", "/user/exist", "/motan/**", "/user/register", "/user/login", "/user/register/fast",
"/token/oneTime", "/user/loginV1", "/user/login/fastV1","/user/**","/api/sms/send_login_code_new_forH5", "/token/oneTime", "/user/loginV1", "/user/login/fastV1","/user/**","/api/sms/send_login_code_new_forH5","/user/lock_ipv4",
"/auth/info/login","/user/login/fast","/user/reset_password", "/user/exist_check","/user/center/**", "/auth/info/login","/user/login/fast","/user/reset_password", "/user/exist_check","/user/center/**",
"/jr58/**", "/app/login", "/app/login_super","/app/login2","/user/login2", "/wechat/**", "/config/**", "/api/**", "/user/exists_token","/query/**", "/jr58/**", "/app/login", "/app/login_super","/app/login2","/user/login2", "/wechat/**", "/config/**", "/api/**", "/user/exists_token","/query/**",
"/platform/api/page/return_url", "/MP_" + "/platform/api/page/return_url", "/MP_" +
......
package cn.quantgroup.xyqb.util; package cn.quantgroup.xyqb.util;
import cn.quantgroup.xyqb.Constants; import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.util.encrypt.MD5Util;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import java.util.Calendar; import java.util.Calendar;
import java.util.Objects;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
...@@ -56,6 +58,31 @@ public class ValidationUtil { ...@@ -56,6 +58,31 @@ public class ValidationUtil {
return matcher.find(); return matcher.find();
} }
/**
* 验证密令
* 私钥 + 操作 + 时
* @param key - Md5密令
* @param lock - true or false
* @return
*/
public static boolean isValid(String key, boolean lock) {
return Objects.equals(key, getMd5Key(lock));
}
/**
* 计算密令
* 私钥 + 操作 + 时
* @param lock - true or false
* @return 加密后的Md5
*/
public static String getMd5Key(boolean lock) {
Calendar today = Calendar.getInstance();
int hour_24 = today.get(Calendar.HOUR_OF_DAY);
StringBuilder _key = new StringBuilder();
_key.append(Constants.CLEAR_LOCK_FOR_IPV4_KEY).append(lock).append(hour_24);
return MD5Util.build(_key.toString());
}
public static boolean isAtDangerousTime() { public static boolean isAtDangerousTime() {
Calendar now = Calendar.getInstance(); Calendar now = Calendar.getInstance();
int hour = now.get(Calendar.HOUR_OF_DAY); int hour = now.get(Calendar.HOUR_OF_DAY);
......
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