Commit fbb8bec3 authored by Java—红包—徐 然's avatar Java—红包—徐 然

Merge branch 'master' into 20171130-forbidden-wechat

# Conflicts:
#	src/main/java/cn/quantgroup/xyqb/Constants.java
#	src/main/java/cn/quantgroup/xyqb/controller/external/user/InnerController.java
parents 5e6176c8 5171d7e9
...@@ -8,30 +8,17 @@ public interface Constants { ...@@ -8,30 +8,17 @@ public interface Constants {
// zero fill with 4 chars... // zero fill with 4 chars...
String ZERO_FILL_TEMPLATE = "%04d"; String ZERO_FILL_TEMPLATE = "%04d";
String PASSWORD_SALT = "_lkb"; String PASSWORD_SALT = "_lkb";
String IMAGE_CAPTCHA_KEY = "img_captcha:"; String IMAGE_CAPTCHA_KEY = "img_captcha:";
String REDIS_CAPTCHA_KEY = "auth:"; String REDIS_CAPTCHA_KEY = "auth:";
String CONFIG_CAPTCHA = "cfg_captcha_%";
// app 后端白名单
String CONFIG_CAPTCHA_WHITEIP_LIST = "cfg_captcha_white_ip_appbackend";
// 每个 IP 每分钟 captcha 限制
String CONFIG_CAPTCHA_PERIP_PERMIN = "cfg_captcha_per_ip_per_min";
// 是否启用万能验证码
String CONFIG_CAPTCHA_MAGIC_CODE_ENABLED = "cfg_captcha_magic_code_enabled";
String REDIS_PREFIX_VERIFICATION_CODE = "verificationCode_"; String REDIS_PREFIX_VERIFICATION_CODE = "verificationCode_";
String REDIS_PREFIX_VERIFICATION_VOICE_CODE = "verificationCode_voice_";
//新版短信验证码计数 //新版短信验证码计数
String REDIS_SMS_CODE_COUNT = "SMS_Phone_verification_code_count:";
String REDIS_SMS_IP_COUNT = "SMS_Ip_verification_code_count:"; String REDIS_SMS_IP_COUNT = "SMS_Ip_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_CODE_COUNT = "Voice_Phone_verification_code_count:";
String REDIS_VOICE_IP_COUNT = "Voice_Ip_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_DEVICE_COUNT = "Voice_Device_verification_code_count:"; String REDIS_VOICE_DEVICE_COUNT = "Voice_Device_verification_code_count:";
String REDIS_VERIFICATION_COUNT = "verification_code_count:"; String REDIS_VERIFICATION_COUNT = "verification_code_count:";
...@@ -39,33 +26,51 @@ public interface Constants { ...@@ -39,33 +26,51 @@ public interface Constants {
Long VERIFICATION_CODE_FINITE_COUNT = 3L; Long VERIFICATION_CODE_FINITE_COUNT = 3L;
String X_AUTH_TOKEN = "x-auth-token"; String X_AUTH_TOKEN = "x-auth-token";
String ONE_TIME_TOKEN = "oneTimeToken";
// -- Start -- IPV4安全策略常量组 // -- Start -- IPV4安全策略常量组
/** 账密不匹配错误 - 按账号计数 */
String REDIS_PASSWORD_ERROR_COUNT = "password_error_count:"; String REDIS_PASSWORD_ERROR_COUNT = "password_error_count:";
/** 账密不匹配错误 - 按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计数 */
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锁 */
String IPV4_LOCK = "lock_ipv4:"; String IPV4_LOCK = "lock_ipv4:";
Long IPV4_LOCK_MINUTES = 3 * 60L; /** 账密不匹配错误 - 锁机制默认参数 - 锁定分钟数 */
Long IPV4_COUNT_MINUTES = 1L; Long IPV4_FAILED_LOCK_MINUTES = 3 * 60L;
Long IPV4_LOCK_ON_COUNTS = 60L; /** 账密不匹配错误 - 锁机制默认参数 - 计数周期 */
Long IPV4_FAILED_COUNT_MINUTES = 1L;
/** 账密不匹配错误 - 锁机制默认参数 - 锁开关阈值 */
Long IPV4_LOCK_ON_FAILED_COUNTS = 60L;
/** 账密匹配成功 - 锁机制默认参数 - 锁定分钟数 */
Long IPV4_SUCCESS_LOCK_MINUTES = 30L;
/** 账密匹配成功 - 锁机制默认参数 - 计数周期 */
Long IPV4_SUCCESS_COUNT_MINUTES = 1 * 60L;
/** 账密匹配成功 - 锁机制默认参数 - 锁开关阈值 */
Long IPV4_LOCK_ON_SUCCESS_COUNTS = 40L;
/** 危险期 - 起始时间(Hour) */
int DANGEROUS_TIME_START = 22; int DANGEROUS_TIME_START = 22;
/** 危险期 - 结束时间(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安全策略常量组
/** /**
* redis中token的key值前缀 * redis中token的key值前缀
*/ */
String SESSION_PREFIX = "spring:session:sessions:"; String SESSION_PREFIX = "spring:session:sessions:";
Long ONE_DAY = 24 * 60 * 60L;
interface Channel { interface Channel {
long LKB = 1; // 量化派
long JR58 = 175; // 58金融
long BAITIAO = 222L; long BAITIAO = 222L;
String LKB_CODE = "0002"; // 量化派channnel_code String LKB_CODE = "0002"; // 量化派channnel_code
long WECHAT = 198L; long WECHAT = 198L;
...@@ -78,15 +83,12 @@ public interface Constants { ...@@ -78,15 +83,12 @@ public interface Constants {
Long ONE_DAY = 24 * 60 * 60L; Long ONE_DAY = 24 * 60 * 60L;
} }
interface WeChat { interface UserAvatar {
String APP_ID = "wx0a7c0bce0c3ac523"; String AVATAR_DEFAULT = "https://avatar.xyqb.com/default_avatar.png";
String REDIRECT_URL = "http://wechattest.xyqb.com/webchat/receiveCode";
String SCOPE = "snsapi_userinfo";
} }
interface UserAvatar {
String AVATAR_DEFAULT = "https://avatar.xyqb.com/default_avatar.png";
}
interface Sms { interface Sms {
String VERIFICATION_CODE = "尊敬的用户,您本次的验证码为:%s,有效期10分钟。"; // 随机验证码 String VERIFICATION_CODE = "尊敬的用户,您本次的验证码为:%s,有效期10分钟。"; // 随机验证码
String BINDCARD_SMS = "用户您好,您已绑卡成功,将会在1-5个工作日内收到借款,请耐心等待。如有疑问,请致电400-002-0061,感谢您对我们的支持";//绑卡成功后的短信文案 String BINDCARD_SMS = "用户您好,您已绑卡成功,将会在1-5个工作日内收到借款,请耐心等待。如有疑问,请致电400-002-0061,感谢您对我们的支持";//绑卡成功后的短信文案
...@@ -94,4 +96,5 @@ public interface Constants { ...@@ -94,4 +96,5 @@ public interface Constants {
} }
String AES_KEY = "ScnmRBhuQpo9kBdn"; String AES_KEY = "ScnmRBhuQpo9kBdn";
} }
package cn.quantgroup.xyqb.aspect.accessable; package cn.quantgroup.xyqb.aspect.accessable;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.model.JsonResult; import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.util.IPUtil; import cn.quantgroup.xyqb.util.IPUtil;
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;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
...@@ -17,15 +22,19 @@ import javax.servlet.http.HttpServletRequest; ...@@ -17,15 +22,19 @@ import javax.servlet.http.HttpServletRequest;
import javax.xml.crypto.dsig.keyinfo.PGPData; import javax.xml.crypto.dsig.keyinfo.PGPData;
/** /**
* Created by 11 on 2017/3/23. * IP白名单检验
*
* @author renwc
* @date 2017-12-01
*/ */
@Aspect @Aspect
@Component @Component
public class IpValidatorAdvisor { public class IpValidateAdvisor {
private static final Logger LOGGER = LoggerFactory.getLogger(IpValidatorAdvisor.class); private static final Logger LOGGER = LoggerFactory.getLogger(IpValidateAdvisor.class);
/*@Value("${config.accessable}") @Autowired
private boolean accessable;*/ @Qualifier("stringRedisTemplate")
private RedisTemplate<String, String> redisTemplate;
@Pointcut("@annotation(cn.quantgroup.xyqb.aspect.accessable.IpValidator)") @Pointcut("@annotation(cn.quantgroup.xyqb.aspect.accessable.IpValidator)")
private void needIpValidate() { private void needIpValidate() {
...@@ -34,26 +43,18 @@ public class IpValidatorAdvisor { ...@@ -34,26 +43,18 @@ public class IpValidatorAdvisor {
@Around("needIpValidate()") @Around("needIpValidate()")
private Object doCapchaValidate(ProceedingJoinPoint pjp) throws Throwable { private Object doCapchaValidate(ProceedingJoinPoint pjp) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
String ip = IPUtil.getRemoteIP(request); // 客户端IP
LOGGER.info("获取ip地址:" + ip); String clientIp = IPUtil.getRemoteIP(request);
if(ip.startsWith("172")||ip.startsWith("192")){ // 白名单
if(IPUtil.whiteOf(clientIp)){
return pjp.proceed(); return pjp.proceed();
} else {
LOGGER.error("非法ip:{}", ip);
return JsonResult.buildErrorStateResult("非法ip", null);
} }
/*HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); // 补充白名单
String ip = IPUtil.getRemoteIP(request); if(redisTemplate.opsForSet().isMember(Constants.IPV4_LOCK_WHITE, clientIp)){
if(accessable) {
return pjp.proceed(); return pjp.proceed();
} else { }
if(ip.startsWith("172")){ IPUtil.logIp(LOGGER, request);
return pjp.proceed(); LOGGER.error("白名单不匹配拦截:ip={}", clientIp);
} else { return JsonResult.buildErrorStateResult("非法访问", null);
LOGGER.error("非法ip:{}", ip);
return JsonResult.buildErrorStateResult("非法ip", null);
}
}*/
//return pjp.proceed();
} }
} }
...@@ -3,7 +3,7 @@ package cn.quantgroup.xyqb.aspect.accessable; ...@@ -3,7 +3,7 @@ package cn.quantgroup.xyqb.aspect.accessable;
import java.lang.annotation.*; import java.lang.annotation.*;
/** /**
* Created by 11 on 2017/3/23. * Ip白名单检验标记
*/ */
@Documented @Documented
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
......
...@@ -4,6 +4,7 @@ package cn.quantgroup.xyqb.aspect.captcha; ...@@ -4,6 +4,7 @@ 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.thirdparty.jcaptcha.AbstractManageableImageCaptchaService; import cn.quantgroup.xyqb.thirdparty.jcaptcha.AbstractManageableImageCaptchaService;
import cn.quantgroup.xyqb.util.IPUtil;
import cn.quantgroup.xyqb.util.ValidationUtil; import cn.quantgroup.xyqb.util.ValidationUtil;
import com.octo.captcha.service.CaptchaServiceException; import com.octo.captcha.service.CaptchaServiceException;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
...@@ -67,7 +68,7 @@ public class CaptchaFiniteValidateAdvisor { ...@@ -67,7 +68,7 @@ public class CaptchaFiniteValidateAdvisor {
/** /**
* 限次图形验证码切面 * 限次图形验证码切面
*/ */
@Pointcut("@annotation(cn.quantgroup.xyqb.aspect.captcha.CaptchaFineteValidator)") @Pointcut("@annotation(cn.quantgroup.xyqb.aspect.captcha.CaptchaFiniteValidator)")
private void needCaptchaFiniteValidate() { private void needCaptchaFiniteValidate() {
} }
...@@ -89,7 +90,7 @@ public class CaptchaFiniteValidateAdvisor { ...@@ -89,7 +90,7 @@ public class CaptchaFiniteValidateAdvisor {
String phoneNo = phonePasswordMap.get("phoneNo"); String phoneNo = phonePasswordMap.get("phoneNo");
Long countErrorByPhone = getCount(phoneNo); Long countErrorByPhone = getCount(phoneNo);
if(countErrorByPhone == null){ if(countErrorByPhone == null){
LOGGER.info("用户名或密码不正确, phoneNo={}, countErrorByPhone={}, clientIp={}", phoneNo, countErrorByPhone, request.getRemoteAddr()); LOGGER.info("用户名或密码不正确, phoneNo={}, countErrorByPhone={}, clientIp={}", phoneNo, countErrorByPhone, IPUtil.getRemoteIP(request));
return JsonResult.buildErrorStateResult("用户名或密码不正确", null); return JsonResult.buildErrorStateResult("用户名或密码不正确", null);
} }
if (countErrorByPhone > Constants.Image_Need_Count) { if (countErrorByPhone > Constants.Image_Need_Count) {
...@@ -97,7 +98,7 @@ public class CaptchaFiniteValidateAdvisor { ...@@ -97,7 +98,7 @@ public class CaptchaFiniteValidateAdvisor {
String captchaId = Optional.ofNullable(request.getParameter("captchaId")).orElse(""); String captchaId = Optional.ofNullable(request.getParameter("captchaId")).orElse("");
String captchaValue = request.getParameter("captchaValue"); String captchaValue = request.getParameter("captchaValue");
if (shouldSkipCaptchaValidate(registerFrom, captchaId, captchaValue)) { if (shouldSkipCaptchaValidate(registerFrom, captchaId, captchaValue)) {
LOGGER.info("使用超级图形验证码校验, registerFrom={}, clientIp={}", registerFrom, request.getRemoteAddr()); LOGGER.info("使用超级图形验证码校验, registerFrom={}, clientIp={}", registerFrom, IPUtil.getRemoteIP(request));
return pjp.proceed(); return pjp.proceed();
} }
if (StringUtils.isNotBlank(captchaValue)) { if (StringUtils.isNotBlank(captchaValue)) {
...@@ -149,10 +150,10 @@ public class CaptchaFiniteValidateAdvisor { ...@@ -149,10 +150,10 @@ public class CaptchaFiniteValidateAdvisor {
} }
/** /**
* 单次令牌参数解析 * 账密参数解析
* *
* @param request 当前请求,其首部行必须包含形如【SingleToken 13461067662:0123456789abcdef】的UTF-8编码的Base64加密参数 * @param request 当前请求
* @return 令牌参数Map 或 null * @return 账密参数Map 或 null
*/ */
private Map<String, String> getHeaderParam(HttpServletRequest request) { private Map<String, String> getHeaderParam(HttpServletRequest request) {
String verificationHeader = "Basic "; String verificationHeader = "Basic ";
......
...@@ -11,5 +11,5 @@ import java.lang.annotation.*; ...@@ -11,5 +11,5 @@ import java.lang.annotation.*;
@Documented @Documented
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface CaptchaFineteValidator { public @interface CaptchaFiniteValidator {
} }
...@@ -4,6 +4,7 @@ import cn.quantgroup.xyqb.Constants; ...@@ -4,6 +4,7 @@ import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.controller.IBaseController; import cn.quantgroup.xyqb.controller.IBaseController;
import cn.quantgroup.xyqb.model.JsonResult; import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.thirdparty.jcaptcha.AbstractManageableImageCaptchaService; import cn.quantgroup.xyqb.thirdparty.jcaptcha.AbstractManageableImageCaptchaService;
import cn.quantgroup.xyqb.util.IPUtil;
import com.octo.captcha.service.CaptchaServiceException; import com.octo.captcha.service.CaptchaServiceException;
import java.io.PipedReader; import java.io.PipedReader;
...@@ -86,15 +87,16 @@ public class CaptchaNewValidateAdvisor { ...@@ -86,15 +87,16 @@ public class CaptchaNewValidateAdvisor {
String captchaValue = request.getParameter("captchaValue"); String captchaValue = request.getParameter("captchaValue");
String phoneNo = request.getParameter("phoneNo"); String phoneNo = request.getParameter("phoneNo");
String deviceId = Optional.ofNullable(request.getParameter("deviceId")).orElse(""); String deviceId = Optional.ofNullable(request.getParameter("deviceId")).orElse("");
String clientIp = getIp(); String clientIp = IPUtil.getRemoteIP(request);
Long countIP = countIP(clientIp); Long countIP = countIP(clientIp);
Long countPhone = countPhone(phoneNo); Long countPhone = countPhone(phoneNo);
Long countDeviceId = countDeviceId(deviceId); Long countDeviceId = countDeviceId(deviceId);
IPUtil.logIp(LOGGER, request);
LOGGER.info("使用图形验证码, registerFrom={}, clientIp={},手机号次数:{},设备次数:{},ip次数:{},phone:{}", registerFrom, clientIp,countPhone,countDeviceId,countIP,phoneNo); LOGGER.info("使用图形验证码, registerFrom={}, clientIp={},手机号次数:{},设备次数:{},ip次数:{},phone:{}", registerFrom, clientIp,countPhone,countDeviceId,countIP,phoneNo);
if (countIP > Constants.Image_Need_Count || countPhone > Constants.Image_Need_Count || countDeviceId > Constants.Image_Need_Count) { //if (countIP > Constants.Image_Need_Count || countPhone > Constants.Image_Need_Count || countDeviceId > Constants.Image_Need_Count) {
if(true){
if (shouldSkipCaptchaValidate(registerFrom, captchaId, captchaValue)) { if (shouldSkipCaptchaValidate(registerFrom, captchaId, captchaValue)) {
LOGGER.info("使用超级图形验证码校验, registerFrom={}, clientIp={}", registerFrom, request.getRemoteAddr()); LOGGER.info("使用超级图形验证码校验, registerFrom={}, clientIp={}", registerFrom, clientIp);
return pjp.proceed(); return pjp.proceed();
} }
...@@ -183,25 +185,6 @@ public class CaptchaNewValidateAdvisor { ...@@ -183,25 +185,6 @@ public class CaptchaNewValidateAdvisor {
} }
} }
private String getIp() {
HttpServletRequest request = getRequest();
String ip = request.getHeader("x-real-ip");
if (StringUtils.isEmpty(ip)) {
ip = request.getRemoteAddr();
}
//过滤反向代理的ip
String[] stemps = ip.split(",");
if (stemps.length >= 1) {
//得到第一个IP,即客户端真实IP
ip = stemps[0];
}
ip = ip.trim();
if (ip.length() > 23) {
ip = ip.substring(0, 23);
}
return ip;
}
private HttpServletRequest getRequest() { private HttpServletRequest getRequest() {
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
return attrs.getRequest(); return attrs.getRequest();
......
...@@ -4,6 +4,7 @@ package cn.quantgroup.xyqb.aspect.captcha; ...@@ -4,6 +4,7 @@ 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.thirdparty.jcaptcha.AbstractManageableImageCaptchaService; import cn.quantgroup.xyqb.thirdparty.jcaptcha.AbstractManageableImageCaptchaService;
import cn.quantgroup.xyqb.util.IPUtil;
import com.octo.captcha.service.CaptchaServiceException; import com.octo.captcha.service.CaptchaServiceException;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.ProceedingJoinPoint;
...@@ -65,7 +66,6 @@ public class CaptchaValidateAdvisor { ...@@ -65,7 +66,6 @@ public class CaptchaValidateAdvisor {
private void needCaptchaValidate() { private void needCaptchaValidate() {
} }
/** /**
* 在受图形验证码保护的接口方法执行前, 执行图形验证码校验 * 在受图形验证码保护的接口方法执行前, 执行图形验证码校验
* *
...@@ -81,7 +81,7 @@ public class CaptchaValidateAdvisor { ...@@ -81,7 +81,7 @@ public class CaptchaValidateAdvisor {
Object captchaValue = request.getParameter("captchaValue"); Object captchaValue = request.getParameter("captchaValue");
if (shouldSkipCaptchaValidate(registerFrom, captchaId, captchaValue)) { if (shouldSkipCaptchaValidate(registerFrom, captchaId, captchaValue)) {
LOGGER.info("使用超级图形验证码校验, registerFrom={}, clientIp={}", registerFrom, request.getRemoteAddr()); LOGGER.info("使用超级图形验证码校验, registerFrom={}, clientIp={}", registerFrom, IPUtil.getRemoteIP(request));
return pjp.proceed(); return pjp.proceed();
} }
......
...@@ -5,7 +5,7 @@ import cn.quantgroup.xyqb.entity.User; ...@@ -5,7 +5,7 @@ import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.model.JsonResult; import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.session.SessionStruct; import cn.quantgroup.xyqb.model.session.SessionStruct;
import cn.quantgroup.xyqb.session.XyqbSessionContextHolder; import cn.quantgroup.xyqb.session.XyqbSessionContextHolder;
import com.alibaba.fastjson.JSONObject; import cn.quantgroup.xyqb.util.IPUtil;
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;
...@@ -32,9 +32,9 @@ import java.util.*; ...@@ -32,9 +32,9 @@ import java.util.*;
*/ */
@Aspect @Aspect
@Component @Component
public class PasswordFreeAccessValidatorValidateAdvisor { public class PasswordFreeAccessValidateAdvisor {
private static final Logger LOGGER = LoggerFactory.getLogger(PasswordFreeAccessValidatorValidateAdvisor.class); private static final Logger LOGGER = LoggerFactory.getLogger(PasswordFreeAccessValidateAdvisor.class);
private static final String PHONE_NO = "phoneNo"; private static final String PHONE_NO = "phoneNo";
private static final String USER_ID = "userId"; private static final String USER_ID = "userId";
...@@ -56,7 +56,7 @@ public class PasswordFreeAccessValidatorValidateAdvisor { ...@@ -56,7 +56,7 @@ public class PasswordFreeAccessValidatorValidateAdvisor {
@Around("passwordFreeAccess()") @Around("passwordFreeAccess()")
private Object checkToken(ProceedingJoinPoint pjp) throws Throwable { private Object checkToken(ProceedingJoinPoint pjp) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
boolean valid = tokenValid(request) || ipValid(request); boolean valid = tokenValid(request);
if (valid) { if (valid) {
return pjp.proceed(); return pjp.proceed();
} }
...@@ -70,59 +70,42 @@ public class PasswordFreeAccessValidatorValidateAdvisor { ...@@ -70,59 +70,42 @@ public class PasswordFreeAccessValidatorValidateAdvisor {
*/ */
private boolean tokenValid(HttpServletRequest request) { private boolean tokenValid(HttpServletRequest request) {
Objects.requireNonNull(request, "无效请求"); Objects.requireNonNull(request, "无效请求");
String clientIp = IPUtil.getRemoteIP(request);
Set<String> paramKeys = request.getParameterMap().keySet(); Set<String> paramKeys = request.getParameterMap().keySet();
if(!paramKeys.contains(PHONE_NO) && !paramKeys.contains(USER_ID)){ if(!paramKeys.contains(PHONE_NO) && !paramKeys.contains(USER_ID)){
LOGGER.info("非法请求 - 缺少参数, paramKeys={}, clientIp={}", paramKeys, request.getRemoteAddr()); LOGGER.info("非法请求 - 缺少参数, paramKeys={}, clientIp={}", paramKeys, clientIp);
return false; return false;
} }
// 当前请求的phoneNo/userId // 当前请求的phoneNo/userId
String phoneNo = request.getParameter(PHONE_NO); String phoneNo = request.getParameter(PHONE_NO);
String userId = request.getParameter(USER_ID); String userId = request.getParameter(USER_ID);
if(StringUtils.isBlank(phoneNo) && StringUtils.isBlank(userId)){ if(StringUtils.isBlank(phoneNo) && StringUtils.isBlank(userId)){
LOGGER.info("非法请求 - 缺少参数, phoneNo={}, userId={}, clientIp={}", phoneNo, userId, request.getRemoteAddr()); LOGGER.info("非法请求 - 缺少参数, phoneNo={}, userId={}, clientIp={}", phoneNo, userId, clientIp);
return false; return false;
} }
// 当前请求的Token // 当前请求的Token
String token = request.getHeader(Constants.X_AUTH_TOKEN); String token = request.getHeader(Constants.X_AUTH_TOKEN);
if (Objects.isNull(token) || token.length() != 36) { if (Objects.isNull(token) || token.length() != 36) {
LOGGER.info("非法请求 - 无效token, token={}, phoneNo={}, userId={}, clientIp={}", token, phoneNo, userId, request.getRemoteAddr()); LOGGER.info("非法请求 - 无效token, token={}, phoneNo={}, userId={}, clientIp={}", token, phoneNo, userId, clientIp);
return false; return false;
} }
// 当前session // 当前session
SessionStruct session = XyqbSessionContextHolder.getXSessionFromRedis(token); SessionStruct session = XyqbSessionContextHolder.getXSessionFromRedis(token);
if (Objects.isNull(session) || Objects.isNull(session.getValues()) || Objects.isNull(session.getValues().getUser())){ if (Objects.isNull(session) || Objects.isNull(session.getValues()) || Objects.isNull(session.getValues().getUser())){
LOGGER.info("非法请求 - 未登录, token={}, phoneNo={}, userId={}, clientIp={}", token, phoneNo, userId, request.getRemoteAddr()); LOGGER.info("非法请求 - 未登录, token={}, phoneNo={}, userId={}, clientIp={}", token, phoneNo, userId, clientIp);
return false; return false;
} }
// 当前用户 // 当前用户
User user = session.getValues().getUser(); User user = session.getValues().getUser();
if(Objects.isNull(user.getId()) && StringUtils.isBlank(user.getPhoneNo())){ if(Objects.isNull(user.getId()) && StringUtils.isBlank(user.getPhoneNo())){
LOGGER.info("非法请求 - 未登录, token={}, phoneNo={}, userId={}, clientIp={}", token, phoneNo, userId, request.getRemoteAddr()); LOGGER.info("非法请求 - 未登录, token={}, phoneNo={}, userId={}, clientIp={}", token, phoneNo, userId, clientIp);
return false; return false;
} }
// 校对用户信息是否匹配 // 校对用户信息是否匹配
boolean valid = (Objects.nonNull(user.getId()) && Objects.equals(userId, user.getId().toString())); boolean valid = (Objects.nonNull(user.getId()) && Objects.equals(userId, user.getId().toString()));
valid = valid || (StringUtils.isNotBlank(phoneNo) && Objects.equals(phoneNo, user.getPhoneNo())); valid = valid || (StringUtils.isNotBlank(phoneNo) && Objects.equals(phoneNo, user.getPhoneNo()));
if(!valid) { if(!valid) {
LOGGER.info("非法请求 - 身份不匹配, token={}, phoneNo=({},{}), userId=({},{}), clientIp={}", token, phoneNo, user.getPhoneNo(), userId, user.getId(), request.getRemoteAddr()); LOGGER.info("非法请求 - 身份不匹配, token={}, phoneNo=({},{}), userId=({},{}), clientIp={}", token, phoneNo, user.getPhoneNo(), userId, user.getId(), clientIp);
}
return valid;
}
/**
* 校验免密访问
* 规则:来访IP与白名单匹配
* @return True or False
*/
private boolean ipValid(HttpServletRequest request) {
Objects.requireNonNull(request, "无效请求");
String remoteAddr = request.getRemoteAddr();
Set<String> whiteAddr = Collections.emptySet();
// Todo 配置白名单
// 校对来访IP是否与白名单匹配
boolean valid = StringUtils.isNotBlank(remoteAddr) && whiteAddr.contains(remoteAddr);
if(!valid) {
LOGGER.info("非法请求 - 未授权访问, clientIp={}", request.getRemoteAddr());
} }
return valid; return valid;
} }
......
...@@ -3,6 +3,7 @@ package cn.quantgroup.xyqb.aspect.lock; ...@@ -3,6 +3,7 @@ package cn.quantgroup.xyqb.aspect.lock;
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.IPUtil;
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;
...@@ -39,7 +40,7 @@ public class PasswordErrorFiniteValidateAdvisor { ...@@ -39,7 +40,7 @@ public class PasswordErrorFiniteValidateAdvisor {
/** /**
* 密码错误限次切面 * 密码错误限次切面
*/ */
@Pointcut("@annotation(cn.quantgroup.xyqb.aspect.lock.PasswordFineteValidator)") @Pointcut("@annotation(cn.quantgroup.xyqb.aspect.lock.PasswordErrorFiniteValidator)")
private void passwordErrorFiniteValidate() { private void passwordErrorFiniteValidate() {
} }
...@@ -58,23 +59,29 @@ public class PasswordErrorFiniteValidateAdvisor { ...@@ -58,23 +59,29 @@ public class PasswordErrorFiniteValidateAdvisor {
}*/ }*/
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 客户端IP // 客户端IP
String clientIp = getIp(request); String clientIp = IPUtil.getRemoteIP(request);
// 入口服务器IP // 白名单
if(StringUtils.startsWith(clientIp, "139.198.")){ if(IPUtil.whiteOf(clientIp)){
return pjp.proceed(); return pjp.proceed();
} }
// 白名单 // 补充白名单
if(redisTemplate.opsForSet().isMember(Constants.IPV4_LOCK_WHITE, clientIp)){ if(redisTemplate.opsForSet().isMember(Constants.IPV4_LOCK_WHITE, clientIp)){
return pjp.proceed(); return pjp.proceed();
} }
// 入口服务器IP
if(StringUtils.startsWith(clientIp, "139.198.")){
return pjp.proceed();
}
// 黑名单 // 黑名单
if(redisTemplate.opsForSet().isMember(Constants.IPV4_LOCK_BLACK, clientIp)){ if(redisTemplate.opsForSet().isMember(Constants.IPV4_LOCK_BLACK, clientIp)){
IPUtil.logIp(LOGGER, request);
LOGGER.info("Lock_ipv4: locked ip access:{}", clientIp); LOGGER.info("Lock_ipv4: locked ip access:{}", clientIp);
return JsonResult.buildErrorStateResult("登录失败", null); return JsonResult.buildErrorStateResult("登录失败", null);
} }
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)){
IPUtil.logIp(LOGGER, request);
LOGGER.info("Lock_ipv4: locked ip access:{}", clientIp); LOGGER.info("Lock_ipv4: locked ip access:{}", clientIp);
return JsonResult.buildErrorStateResult("登录失败", null); return JsonResult.buildErrorStateResult("登录失败", null);
} }
...@@ -85,30 +92,4 @@ public class PasswordErrorFiniteValidateAdvisor { ...@@ -85,30 +92,4 @@ public class PasswordErrorFiniteValidateAdvisor {
return Constants.IPV4_LOCK + ipv4; return Constants.IPV4_LOCK + ipv4;
} }
/**
* 客户端IP解析
*
* @param request 当前请求,其首部行必须包含形如【SingleToken 13461067662:0123456789abcdef】的UTF-8编码的Base64加密参数
* @return 客户端IP 或 null
*/
private String getIp(HttpServletRequest request) {
Objects.requireNonNull(request, "无效请求");
String ip = request.getHeader("x-real-ip");
if (StringUtils.isBlank(ip)) {
ip = request.getRemoteAddr();
}
//过滤反向代理的ip
String[] stemps = ip.split(",");
if (stemps.length >= 1) {
//得到第一个IP,即客户端真实IP
ip = stemps[0];
}
ip = ip.trim();
if (ip.length() > 23) {
ip = ip.substring(0, 23);
}
return ip;
}
} }
...@@ -11,5 +11,5 @@ import java.lang.annotation.*; ...@@ -11,5 +11,5 @@ import java.lang.annotation.*;
@Documented @Documented
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface PasswordFineteValidator { public @interface PasswordErrorFiniteValidator {
} }
package cn.quantgroup.xyqb.aspect.token;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.model.JsonResult;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
/**
* 一次性令牌校验切面
*
* @author 任文超
* @version 1.0.0
* @since 2017-10-31
*/
@Aspect
@Component
public class OneTimeTokenValidateAdvisor {
private static final Logger LOGGER = LoggerFactory.getLogger(OneTimeTokenValidateAdvisor.class);
@Autowired
@Qualifier("stringRedisTemplate")
private RedisTemplate<String, String> redisTemplate;
/**
* 一次性令牌校验切面
*/
@Pointcut("@annotation(cn.quantgroup.xyqb.aspect.token.OneTimeTokenValidator)")
private void needOneTimeToken() {}
/**
* 在受一次性令牌保护的接口方法执行前, 执行一次性令牌校验
*
* @throws Throwable
*/
@Around("needOneTimeToken()")
private Object checkOneTimeToken(ProceedingJoinPoint pjp) throws Throwable {
boolean valid = oneTimeTokenValid();
if (valid) {
return pjp.proceed();
}
return JsonResult.buildSuccessResult("操作失败,请重新提交", "", 2L);
}
/**
* 校验一次性令牌
* @return True or False
*/
private boolean oneTimeTokenValid() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 当前请求的OneTimeToken
String oneTimeToken = request.getParameter(Constants.ONE_TIME_TOKEN);
if (StringUtils.isBlank(oneTimeToken)){
return false;
}
String oneTimeToken_value = redisTemplate.opsForValue().get(oneTimeToken);
// OneTimeToken再Redis中值不应为空值(空白、空格、null)
if (StringUtils.isBlank(oneTimeToken_value)) {
return false;
}
boolean valid = Objects.equals(Boolean.TRUE.toString(), oneTimeToken_value);
// OneTimeToken校验正确时删除key
if(valid) {
redisTemplate.delete(oneTimeToken);
}else {
LOGGER.info("令牌已失效,请重新请求, oneTimeToken={}, clientIp={}", oneTimeToken, request.getRemoteAddr());
}
return valid;
}
}
package cn.quantgroup.xyqb.aspect.token;
import java.lang.annotation.*;
/**
* 一次性令牌校验标记
* @author 任文超
* @version 1.0.0
* @since 2017-10-31
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OneTimeTokenValidator {
}
...@@ -2,6 +2,7 @@ package cn.quantgroup.xyqb.controller; ...@@ -2,6 +2,7 @@ package cn.quantgroup.xyqb.controller;
import cn.quantgroup.xyqb.entity.User; import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.model.session.SessionStruct; import cn.quantgroup.xyqb.model.session.SessionStruct;
import cn.quantgroup.xyqb.util.IPUtil;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
...@@ -50,25 +51,7 @@ public interface IBaseController { ...@@ -50,25 +51,7 @@ public interface IBaseController {
default String getIp() { default String getIp() {
HttpServletRequest request = getRequest(); HttpServletRequest request = getRequest();
return IPUtil.getRemoteIP(request);
String ip = request.getHeader("x-real-ip");
if (StringUtils.isEmpty(ip)) {
ip = request.getRemoteAddr();
}
//过滤反向代理的ip
String[] stemps = ip.split(",");
if (stemps.length >= 1) {
//得到第一个IP,即客户端真实IP
ip = stemps[0];
}
ip = ip.trim();
if (ip.length() > 23) {
ip = ip.substring(0, 23);
}
return ip;
} }
default String getProtocol() { default String getProtocol() {
......
...@@ -30,7 +30,6 @@ import java.io.IOException; ...@@ -30,7 +30,6 @@ import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import sun.management.counter.LongCounter;
/** /**
* 类名称:ImgCaptchaController * 类名称:ImgCaptchaController
......
...@@ -76,12 +76,6 @@ public class LockIpv4Controller implements IBaseController { ...@@ -76,12 +76,6 @@ public class LockIpv4Controller implements IBaseController {
// 操作标记 // 操作标记
boolean lock = Objects.equals(Boolean.TRUE.toString(), act); boolean lock = Objects.equals(Boolean.TRUE.toString(), act);
boolean valid = ValidationUtil.isValid(key, lock); boolean valid = ValidationUtil.isValid(key, lock);
// Todo - 兼容简单验证规则,暂时保留
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){ if(valid){
lockIpv4(ip, lock); lockIpv4(ip, lock);
return JsonResult.buildSuccessResult("Success",null); return JsonResult.buildSuccessResult("Success",null);
...@@ -101,19 +95,19 @@ public class LockIpv4Controller implements IBaseController { ...@@ -101,19 +95,19 @@ public class LockIpv4Controller implements IBaseController {
String lockIpv4Key = getLockIpv4Key(ip); String lockIpv4Key = getLockIpv4Key(ip);
if(lock){ if(lock){
// 每分钟计数阈值 // 每分钟计数阈值
long counts = Constants.IPV4_LOCK_ON_COUNTS; long counts = Constants.IPV4_LOCK_ON_FAILED_COUNTS;
String redisCounts = redisTemplate.opsForValue().get(Constants.IPV4_LOCK_ON_COUNTS_REDIS); String redisCounts = redisTemplate.opsForValue().get(Constants.IPV4_LOCK_ON_COUNTS_REDIS);
if(StringUtils.isNumeric(redisCounts) && Integer.valueOf(redisCounts) > 0){ if(StringUtils.isNumeric(redisCounts) && Integer.valueOf(redisCounts) > 0){
counts = Integer.valueOf(redisCounts); counts = Integer.valueOf(redisCounts);
} }
// 锁定时长 // 锁定时长
long minutes = Constants.IPV4_LOCK_MINUTES; long minutes = Constants.IPV4_FAILED_LOCK_MINUTES;
String redisMinutes = redisTemplate.opsForValue().get(Constants.IPV4_LOCK_ON_COUNTS_REDIS); String redisMinutes = redisTemplate.opsForValue().get(Constants.IPV4_LOCK_ON_COUNTS_REDIS);
if(StringUtils.isNumeric(redisMinutes) && Integer.valueOf(redisMinutes) > 0){ if(StringUtils.isNumeric(redisMinutes) && Integer.valueOf(redisMinutes) > 0){
minutes = Integer.valueOf(redisMinutes); minutes = Integer.valueOf(redisMinutes);
} }
redisTemplate.opsForValue().set(lockIpv4Key, Boolean.TRUE.toString(), minutes, TimeUnit.MINUTES); redisTemplate.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_COUNT_MINUTES, minutes); LOGGER.info("Lock_ipv4: locked ip access:{}, error overstep {} times in {} minutes, do lock {} minutes", ip, counts, Constants.IPV4_FAILED_COUNT_MINUTES, minutes);
}else{ }else{
redisTemplate.delete(lockIpv4Key); redisTemplate.delete(lockIpv4Key);
LOGGER.info("Lock_ipv4: unlocked ip Success. ip:{}", ip); LOGGER.info("Lock_ipv4: unlocked ip Success. ip:{}", ip);
...@@ -239,7 +233,7 @@ public class LockIpv4Controller implements IBaseController { ...@@ -239,7 +233,7 @@ public class LockIpv4Controller implements IBaseController {
}else{ }else{
redisTemplate.delete(Constants.IPV4_LOCK_ON_COUNTS_REDIS); redisTemplate.delete(Constants.IPV4_LOCK_ON_COUNTS_REDIS);
redisTemplate.delete(Constants.IPV4_LOCK_MINUTES_REDIS); redisTemplate.delete(Constants.IPV4_LOCK_MINUTES_REDIS);
LOGGER.info("Lock_ipv4: remove redis-param counts、minutes Success, counts:{},minutes:{}, current default:[counts:{},minutes:{}]", Constants.IPV4_LOCK_ON_COUNTS, Constants.IPV4_LOCK_MINUTES); LOGGER.info("Lock_ipv4: remove redis-param counts、minutes Success, counts:{},minutes:{}, current default:[counts:{},minutes:{}]", Constants.IPV4_LOCK_ON_FAILED_COUNTS, Constants.IPV4_FAILED_LOCK_MINUTES);
} }
} }
......
...@@ -83,8 +83,7 @@ public class AppController implements IBaseController { ...@@ -83,8 +83,7 @@ public class AppController implements IBaseController {
return JsonResult.buildErrorStateResult(USER_ERROR_OR_PASSWORD_ERROR, null); return JsonResult.buildErrorStateResult(USER_ERROR_OR_PASSWORD_ERROR, null);
} }
String requestIp = IPUtil.getRemoteIP(request); LOGGER.info("app/login第三方用户登录, loginFrom:{},channelId:{},btRegisterChannelId:{} requestIp:{},idNo:{},name:{}", registerFrom,channelId,btRegisterChannelId, IPUtil.getRemoteIP(request),idNo,name);
LOGGER.info("app/login第三方用户登录, loginFrom:{},channelId:{},btRegisterChannelId:{} requestIp:{},idNo:{},name:{}", registerFrom,channelId,btRegisterChannelId, requestIp,idNo,name);
User user = userService.findByPhoneInDb(phoneNo); User user = userService.findByPhoneInDb(phoneNo);
if (user == null) { if (user == null) {
user = register(registerFrom, phoneNo, idNo, name, channelId,btRegisterChannelId); user = register(registerFrom, phoneNo, idNo, name, channelId,btRegisterChannelId);
...@@ -129,8 +128,7 @@ public class AppController implements IBaseController { ...@@ -129,8 +128,7 @@ public class AppController implements IBaseController {
return JsonResult.buildErrorStateResult(USER_ERROR_OR_PASSWORD_ERROR, null); return JsonResult.buildErrorStateResult(USER_ERROR_OR_PASSWORD_ERROR, null);
} }
String requestIp = IPUtil.getRemoteIP(request); LOGGER.info("第三方用户登录, loginFrom:{},channelId:{}, requestIp:{}", registerFrom,channelId, IPUtil.getRemoteIP(request));
LOGGER.info("第三方用户登录, loginFrom:{},channelId:{}, requestIp:{}", registerFrom,channelId, requestIp);
User user = userService.findByPhoneInDb(phoneNo); User user = userService.findByPhoneInDb(phoneNo);
if (user == null) { if (user == null) {
...@@ -168,8 +166,7 @@ public class AppController implements IBaseController { ...@@ -168,8 +166,7 @@ public class AppController implements IBaseController {
return JsonResult.buildErrorStateResult(USER_ERROR_OR_PASSWORD_ERROR, null); return JsonResult.buildErrorStateResult(USER_ERROR_OR_PASSWORD_ERROR, null);
} }
String requestIp = IPUtil.getRemoteIP(request); LOGGER.info("app/login_super第三方用户登录, loginFrom:{},channelId:{},btRegisterChannelId:{} requestIp:{},idNo:{},name:{}", registerFrom,channelId,btRegisterChannelId, IPUtil.getRemoteIP(request),idNo,name);
LOGGER.info("app/login_super第三方用户登录, loginFrom:{},channelId:{},btRegisterChannelId:{} requestIp:{},idNo:{},name:{}", registerFrom,channelId,btRegisterChannelId, requestIp,idNo,name);
User user = userService.findByPhoneInDb(phoneNo); User user = userService.findByPhoneInDb(phoneNo);
if (user == null) { if (user == null) {
user = register(registerFrom, phoneNo, idNo, name, channelId,btRegisterChannelId); user = register(registerFrom, phoneNo, idNo, name, channelId,btRegisterChannelId);
......
package cn.quantgroup.xyqb.controller.external.user; package cn.quantgroup.xyqb.controller.external.user;
import cn.quantgroup.user.enums.Relation; import cn.quantgroup.user.enums.Relation;
import cn.quantgroup.xyqb.Constants; import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.aspect.limit.PasswordFreeAccessValidator; import cn.quantgroup.xyqb.aspect.accessable.IpValidator;
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;
import cn.quantgroup.xyqb.entity.*; import cn.quantgroup.xyqb.entity.*;
...@@ -426,8 +427,7 @@ public class InnerController implements IBaseController { ...@@ -426,8 +427,7 @@ public class InnerController implements IBaseController {
return JsonResult.buildErrorStateResult("修改联系人不存在", null); return JsonResult.buildErrorStateResult("修改联系人不存在", null);
} }
contact = contactService.saveContact(name, phoneNo, relation, contact); contact = contactService.saveContact(name, phoneNo, relation, contact);
String ip= IPUtil.getRemoteIP(request); LOGGER.info("修改后联系人信息:{},修改原因:{},操作ip:{}",contact,reason,IPUtil.getRemoteIP(request));
LOGGER.info("修改后联系人信息:{},修改原因:{},操作ip:{}",contact,reason,ip);
return JsonResult.buildSuccessResult("修改联系人成功", contact); return JsonResult.buildSuccessResult("修改联系人成功", contact);
} }
...@@ -524,9 +524,9 @@ public class InnerController implements IBaseController { ...@@ -524,9 +524,9 @@ public class InnerController implements IBaseController {
return JsonResult.buildSuccessResult(null, UserExtInfoRet.getUserExtInfoRet(info)); return JsonResult.buildSuccessResult(null, UserExtInfoRet.getUserExtInfoRet(info));
} }
// Todo @PasswordFreeAccessValidator @IpValidator
@RequestMapping("/user_detail/search_list")
@LogHttpCaller @LogHttpCaller
@RequestMapping("/user_detail/search_list")
public JsonResult searchUserDetailList(String name, String phoneNo, String idNo) { public JsonResult searchUserDetailList(String name, String phoneNo, String idNo) {
LOGGER.info("searchUserDetailList ,param.name:{},phone:{},idNo:{},ip:{}", name, phoneNo, idNo, getIp()); LOGGER.info("searchUserDetailList ,param.name:{},phone:{},idNo:{},ip:{}", name, phoneNo, idNo, getIp());
...@@ -578,9 +578,9 @@ public class InnerController implements IBaseController { ...@@ -578,9 +578,9 @@ public class InnerController implements IBaseController {
return JsonResult.buildSuccessResult("success", wechatUserInfo.getOpenId()); return JsonResult.buildSuccessResult("success", wechatUserInfo.getOpenId());
} }
// Todo @PasswordFreeAccessValidator @IpValidator
@RequestMapping("/user-association/search/phone")
@LogHttpCaller @LogHttpCaller
@RequestMapping("/user-association/search/phone")
public JsonResult findUserAssociationByPhone(String phoneNo) { public JsonResult findUserAssociationByPhone(String phoneNo) {
UserDetail userDetail = userDetailService.findByPhoneNo(phoneNo); UserDetail userDetail = userDetailService.findByPhoneNo(phoneNo);
UserAssociation bean = new UserAssociation(); UserAssociation bean = new UserAssociation();
...@@ -874,7 +874,7 @@ public class InnerController implements IBaseController { ...@@ -874,7 +874,7 @@ public class InnerController implements IBaseController {
String district, String district,
String address, String address,
String contacts) { String contacts) {
LOGGER.info("保存用户、联系人、地址信息:registeredFrom:[{}], phoneNo[{}],name[{}],idNo[{}],provinceCode[{}],cityCode[{}],districtCode[{}]," + LOGGER.info("[/innerapi/user/save_multi]保存用户、联系人、地址信息:registeredFrom:[{}], phoneNo[{}],name[{}],idNo[{}],provinceCode[{}],cityCode[{}],districtCode[{}]," +
"address[{}],contacts[{}]", registeredFrom, phoneNo, name, idNo, provinceCode, cityCode, districtCode, address, contacts); "address[{}],contacts[{}]", registeredFrom, phoneNo, name, idNo, provinceCode, cityCode, districtCode, address, contacts);
if (!NumberUtils.isDigits(registeredFrom)) { if (!NumberUtils.isDigits(registeredFrom)) {
...@@ -936,6 +936,7 @@ public class InnerController implements IBaseController { ...@@ -936,6 +936,7 @@ public class InnerController implements IBaseController {
if (!ValidationUtil.validatePhoneNo(phoneNo)) { if (!ValidationUtil.validatePhoneNo(phoneNo)) {
return JsonResult.buildErrorStateResult("手机号不正确", null); return JsonResult.buildErrorStateResult("手机号不正确", null);
} }
LOGGER.info("[/innerapi/user/register]channelId={},ip={}", channelId, getIp());
User user = userService.findByPhoneInDb(phoneNo); User user = userService.findByPhoneInDb(phoneNo);
if (user == null) { if (user == null) {
user = userService.registerAndReturn(phoneNo, StringUtils.defaultString(password, ""), channelId); user = userService.registerAndReturn(phoneNo, StringUtils.defaultString(password, ""), channelId);
......
package cn.quantgroup.xyqb.controller.internal.token;
import cn.quantgroup.xyqb.controller.IBaseController;
import cn.quantgroup.xyqb.model.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* 发放一次性令牌
*
* @author 任文超
* @version 1.0.0
* @since 2017-10-31
*/
@RestController
@RequestMapping("/token")
public class OneTimeTokenController implements IBaseController {
private static final Long SECONDS = 5 * 60L;
@Autowired
@Qualifier("stringRedisTemplate")
private RedisTemplate<String, String> redisTemplate;
/**
* 发放一枚一次性令牌
* One-Time Token用法:http请求首部行添加参数{One-Time-Token 6ac0665b-e19c-4392-a244-7b61690833f5}
*
* @return 一次性令牌
*/
@RequestMapping(value = "/oneTime")
public JsonResult oneTimeToken() {
String token = UUID.randomUUID().toString();
redisTemplate.opsForValue().set(token, Boolean.TRUE.toString(), SECONDS, TimeUnit.SECONDS);
return JsonResult.buildSuccessResult("", token);
}
}
...@@ -34,7 +34,9 @@ public class IPWhiteListInterceptor implements HandlerInterceptor { ...@@ -34,7 +34,9 @@ public class IPWhiteListInterceptor implements HandlerInterceptor {
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(isDebug !=0) return true; if(isDebug !=0){
return true;
}
String remoteIP = IPUtil.getRemoteIP(request); String remoteIP = IPUtil.getRemoteIP(request);
if(StringUtils.isNoneBlank(remoteIP)){ if(StringUtils.isNoneBlank(remoteIP)){
remoteIP = remoteIP.trim(); remoteIP = remoteIP.trim();
......
package cn.quantgroup.xyqb.service.user;
/**
* IPV4锁机制Service
* @author renwc
*/
public interface ILockIpv4Service {
/**
* 向该phoneNo添加错误计数器
* @param phoneNo
*/
void countErrorByPhoneNo(String phoneNo);
/**
* 向该ipv4添加错误计数器
* @param ip - 目标ip
*/
void countErrorByIpv4(String ip);
/**
* 锁定IPV4
* @param ip - 目标ip
* @param count - 错误计数
*/
void lockErrorIpv4(String ip, long count);
/**
* 向该phoneNo添加错误计数器
* @param ip - 目标ip
*/
void countSuccessByIpv4(String ip);
/**
* 锁定IPV4
* @param ip - 目标ip
* @param count - 错误计数
*/
void lockSuccessIpv4(String ip, long count);
}
package cn.quantgroup.xyqb.service.user.impl;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.exception.PasswordErrorLimitException;
import cn.quantgroup.xyqb.service.user.ILockIpv4Service;
import cn.quantgroup.xyqb.util.DateUtils;
import cn.quantgroup.xyqb.util.IPUtil;
import cn.quantgroup.xyqb.util.ValidationUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* IPV4锁机制Service实现
* @author renwc
*/
@Service
public class LockIpv4ServiceImpl implements ILockIpv4Service {
private static final Logger LOGGER = LoggerFactory.getLogger(ILockIpv4Service.class);
@Autowired
@Qualifier("stringRedisTemplate")
private RedisTemplate<String, String> stringRedisTemplate;
@Override
public void countErrorByPhoneNo(String phoneNo) {
// 密码错误时,给该账号添加计数器
String key = Constants.REDIS_PASSWORD_ERROR_COUNT + 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) {
LOGGER.info("用户名或密码不正确,phoneNo={}", phoneNo);
throw new PasswordErrorLimitException("用户名或密码不正确");
} else if (Objects.equals(errorCount, Constants.Image_Need_Count)) {
LOGGER.info("请输入图形验证码,phoneNo={}", phoneNo);
throw new PasswordErrorLimitException("请输入图形验证码");
}
}
/**
* 对白名单之外的所有公有、私有IP执行错误计数
* @param ipv4
*/
@Override
public void countErrorByIpv4(String ipv4) {
// Todo -- 全天候开放监控
/*if(!ValidationUtil.isAtDangerousTime()){
return;
}*/
if (ValidationUtil.validateIpv4(ipv4) && !IPUtil.whiteOf(ipv4)) {
String ipv4Key = getErrorIpKey(ipv4);
if(!stringRedisTemplate.hasKey(ipv4Key)){
// 计数周期1分钟
stringRedisTemplate.opsForValue().set(ipv4Key, String.valueOf(0), Constants.IPV4_FAILED_COUNT_MINUTES, TimeUnit.MINUTES);
}
Long count = stringRedisTemplate.opsForValue().increment(ipv4Key, 1L);
LOGGER.info("Lock_ipv4: count error ip access: ip={}, count={}", ipv4, count);
lockErrorIpv4(ipv4, count);
}
}
@Override
public void lockErrorIpv4(String ip, long count){
// 每分钟计数阈值
long counts = Constants.IPV4_LOCK_ON_FAILED_COUNTS;
String redisCounts = stringRedisTemplate.opsForValue().get(Constants.IPV4_LOCK_ON_COUNTS_REDIS);
if(StringUtils.isNumeric(redisCounts) && Integer.valueOf(redisCounts) > 0){
counts = Integer.valueOf(redisCounts);
}
if(count < counts){
return;
}
// 锁定时长
long minutes = Constants.IPV4_FAILED_LOCK_MINUTES;
String redisMinutes = stringRedisTemplate.opsForValue().get(Constants.IPV4_LOCK_ON_COUNTS_REDIS);
if(StringUtils.isNumeric(redisMinutes) && Integer.valueOf(redisMinutes) > 0){
minutes = Integer.valueOf(redisMinutes);
}
String lockIpv4Key = getLockIpv4Key(ip);
stringRedisTemplate.opsForValue().set(lockIpv4Key, Boolean.TRUE.toString(), minutes, TimeUnit.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);
}
/**
* 对白名单之外的所有公有、私有IP执行成功计数
* @param ipv4
*/
@Override
public void countSuccessByIpv4(String ipv4) {
// Todo -- 全天候开放监控
/*if(!ValidationUtil.isAtDangerousTime()){
return;
}*/
if (ValidationUtil.validateIpv4(ipv4) && !IPUtil.whiteOf(ipv4)) {
String ipv4Key = getSuccessIpKey(ipv4);
if(!stringRedisTemplate.hasKey(ipv4Key)){
// 计数周期1分钟
stringRedisTemplate.opsForValue().set(ipv4Key, String.valueOf(0), Constants.IPV4_SUCCESS_COUNT_MINUTES, TimeUnit.MINUTES);
}
Long count = stringRedisTemplate.opsForValue().increment(ipv4Key, 1L);
LOGGER.info("Lock_ipv4: count success ip access: ip={}, count={}", ipv4, count);
lockSuccessIpv4(ipv4, count);
}
}
@Override
public void lockSuccessIpv4(String ip, long count){
// 每小时计数阈值
if(count < Constants.IPV4_LOCK_ON_SUCCESS_COUNTS){
return;
}
// 锁定时长
String lockIpv4Key = getLockIpv4Key(ip);
stringRedisTemplate.opsForValue().set(lockIpv4Key, Boolean.TRUE.toString(), Constants.IPV4_SUCCESS_LOCK_MINUTES, TimeUnit.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){
return Constants.REDIS_PASSWORD_ERROR_COUNT_FOR_IPV4 + ipv4;
}
private final static String getSuccessIpKey(String ipv4){
return Constants.REDIS_PASSWORD_SUCCESS_COUNT_FOR_IPV4 + ipv4;
}
private final static String getLockIpv4Key(String ipv4){
return Constants.IPV4_LOCK + ipv4;
}
}
package cn.quantgroup.xyqb.util; package cn.quantgroup.xyqb.util;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Collections;
import java.util.Objects;
import java.util.Set;
/** /**
* IP地址工具类 * IP地址工具类
* *
* @author mengfan.feng * @author renwc
* @time 2015-10-27 11:41 * @date 2017-12-01
*/ */
public class IPUtil { public class IPUtil {
/**
* IP白名单
*
* 192.168.3.0/24 - 公有云测试业务
* 192.168.4.0/24 - 公有云测试业务
* 172.16.0.0/16 - 公有云正式业务
* 172.20.0.0/16 - 3B私有云
* 172.30.0.0/16 - 3C私有云
*/
private static final Set<String> whiteAddr = Sets.newHashSet();
static {
String[] ips = {"172.16.", "172.20.", "172.30.", "192.168.3.", "192.168.4."};
whiteAddr.addAll(Arrays.asList(ips));
}
/**
* 判断是否为白名单IP
* @param ipv4
* @return
*/
public static final boolean whiteOf(String ipv4){
if(ValidationUtil.validateIpv4(ipv4)){
for(String ipField : whiteAddr){
if(ipv4.startsWith(ipField)){
return true;
}
}
}
return false;
}
/** /**
* 通过指定请求获得对应的远程ip地址 * 打印IP
* @param logger - 日志记录器
* @param request - 真实HttpServletRequest请求
*/
public static final void logIp(Logger logger, HttpServletRequest request) {
if(Objects.isNull(request)){
return;
}
String remoteAddr = request.getRemoteAddr();
String xRealIp = IPUtil.getRemoteIP(request);
String xOriginalClientIp = request.getHeader("x-original-client-ip");
logger.info("Test ips:[client={}, old={}, new={}]", remoteAddr, xRealIp, xOriginalClientIp);
}
/**
* 获取请求客户端的真实ip地址
* *
* @param request * @param request
* @return * @return
*/ */
public static String getRemoteIP(HttpServletRequest request) { public static String getRemoteIP(HttpServletRequest request) {
String ip = request.getHeader("x-real-ip"); String ip = request.getHeader("x-original-client-ip");
if (ValidationUtil.validateIpv4(ip) && !ip.startsWith("127.")) {
return ip;
}
// Todo - 以下为老代码,保留容错
ip = request.getHeader("x-real-ip");
if (StringUtils.isEmpty(ip)) { if (StringUtils.isEmpty(ip)) {
ip = request.getRemoteAddr(); ip = request.getRemoteAddr();
} }
//过滤反向代理的ip //过滤反向代理的ip
String[] stemps = ip.split(","); String[] stemps = ip.split(",");
if (stemps != null && stemps.length >= 1) { if (stemps != null && stemps.length >= 1) {
//得到第一个IP,即客户端真实IP //得到第一个IP,即客户端真实IP
ip = stemps[0]; ip = stemps[0];
} }
ip = ip.trim(); ip = ip.trim();
if (ip.length() > 23) { if (ip.length() > 23) {
ip = ip.substring(0, 23); ip = ip.substring(0, 23);
} }
return ip; return ip;
} }
} }
...@@ -18,7 +18,7 @@ public class ValidationUtil { ...@@ -18,7 +18,7 @@ public class ValidationUtil {
private static String phoneRegExp = "^((13[0-9])|(14[0-9])|(15[0-9])|(17[0-9])|(18[0-9])|(19[0-9]))\\d{8}$"; private static String phoneRegExp = "^((13[0-9])|(14[0-9])|(15[0-9])|(17[0-9])|(18[0-9])|(19[0-9]))\\d{8}$";
private static String chineseNameRegExp = "^[\u4e00-\u9fa5]+(\\.|·)?[\u4e00-\u9fa5]+$"; private static String chineseNameRegExp = "^[\u4e00-\u9fa5]+(\\.|·)?[\u4e00-\u9fa5]+$";
private static String ipv4RegExp = "^((2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)\\.){3}(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)$"; private static String ipv4RegExp = "^((2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)\\.){3}(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)$";
private static String localIpv4RegExp = "^172(\\.(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)){3}$"; private static String localIpv4RegExp = "^((172\\.(1[0-6]|2[0-9]|3[01]))|(192\\.168|169\\.254)|((127|10)\\.(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)))(\\.(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)){2}$";
private static Pattern phonePattern = Pattern.compile(phoneRegExp); private static Pattern phonePattern = Pattern.compile(phoneRegExp);
private static Pattern chinesePattern = Pattern.compile(chineseNameRegExp); private static Pattern chinesePattern = Pattern.compile(chineseNameRegExp);
......
...@@ -111,7 +111,6 @@ public class LoginForH5Tests { ...@@ -111,7 +111,6 @@ public class LoginForH5Tests {
// 第一次使用TokenOnce // 第一次使用TokenOnce
String aspectUri = "/user/login/fastForH5"; String aspectUri = "/user/login/fastForH5";
mvcResult = mvc.perform(MockMvcRequestBuilders.get(aspectUri).accept(MediaType.APPLICATION_JSON) mvcResult = mvc.perform(MockMvcRequestBuilders.get(aspectUri).accept(MediaType.APPLICATION_JSON)
.header(Constants.ONE_TIME_TOKEN, oneTimeToken)
.header("authorization", authorization)) .header("authorization", authorization))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andReturn(); .andReturn();
...@@ -123,7 +122,6 @@ public class LoginForH5Tests { ...@@ -123,7 +122,6 @@ public class LoginForH5Tests {
Assert.assertNotEquals("0002", businessCode); Assert.assertNotEquals("0002", businessCode);
// 使用过期的TokenOnce与verificationCode // 使用过期的TokenOnce与verificationCode
mvcResult = mvc.perform(MockMvcRequestBuilders.get(aspectUri).accept(MediaType.APPLICATION_JSON) mvcResult = mvc.perform(MockMvcRequestBuilders.get(aspectUri).accept(MediaType.APPLICATION_JSON)
.header(Constants.ONE_TIME_TOKEN, oneTimeToken)
.header("authorization", authorization)) .header("authorization", authorization))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andReturn(); .andReturn();
......
...@@ -98,7 +98,6 @@ public class OneTimeTokenTests { ...@@ -98,7 +98,6 @@ public class OneTimeTokenTests {
// 第一次使用OneTime-Token // 第一次使用OneTime-Token
String aspectUri = "/user/loginForH5"; String aspectUri = "/user/loginForH5";
mvcResult = mvc.perform(MockMvcRequestBuilders.get(aspectUri).accept(MediaType.APPLICATION_JSON) mvcResult = mvc.perform(MockMvcRequestBuilders.get(aspectUri).accept(MediaType.APPLICATION_JSON)
.param(Constants.ONE_TIME_TOKEN, oneTimeToken)
.param("phoneNo", userName) .param("phoneNo", userName)
.param("password", password)) .param("password", password))
.andExpect(status().isOk()) .andExpect(status().isOk())
...@@ -111,7 +110,6 @@ public class OneTimeTokenTests { ...@@ -111,7 +110,6 @@ public class OneTimeTokenTests {
Assert.assertNotEquals("0002", businessCode); Assert.assertNotEquals("0002", businessCode);
// 使用过期的TokenOnce // 使用过期的TokenOnce
mvcResult = mvc.perform(MockMvcRequestBuilders.get(aspectUri).accept(MediaType.APPLICATION_JSON) mvcResult = mvc.perform(MockMvcRequestBuilders.get(aspectUri).accept(MediaType.APPLICATION_JSON)
.param(Constants.ONE_TIME_TOKEN, oneTimeToken)
.param("phoneNo", userName) .param("phoneNo", userName)
.param("password", password)) .param("password", password))
.andExpect(status().isOk()) .andExpect(status().isOk())
......
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