Commit cdb2fe25 authored by 技术部-任文超's avatar 技术部-任文超
parent d457a892
...@@ -39,7 +39,6 @@ public interface Constants { ...@@ -39,7 +39,6 @@ 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:";
......
...@@ -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)
......
package cn.quantgroup.xyqb.aspect.accessable;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.util.IPUtil;
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.Value;
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 javax.xml.crypto.dsig.keyinfo.PGPData;
/**
* Created by 11 on 2017/3/23.
*/
@Aspect
@Component
public class IpValidatorAdvisor {
private static final Logger LOGGER = LoggerFactory.getLogger(IpValidatorAdvisor.class);
/*@Value("${config.accessable}")
private boolean accessable;*/
@Pointcut("@annotation(cn.quantgroup.xyqb.aspect.accessable.IpValidator)")
private void needIpValidate() {
}
@Around("needIpValidate()")
private Object doCapchaValidate(ProceedingJoinPoint pjp) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
String ip = IPUtil.getRemoteIP(request);
LOGGER.info("获取ip地址:" + ip);
if(ip.startsWith("172")||ip.startsWith("192")){
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(accessable) {
return pjp.proceed();
} else {
if(ip.startsWith("172")){
return pjp.proceed();
} else {
LOGGER.error("非法ip:{}", ip);
return JsonResult.buildErrorStateResult("非法ip", null);
}
}*/
//return pjp.proceed();
}
}
package cn.quantgroup.xyqb.aspect.captcha;
import java.lang.annotation.*;
/**
* 限次的图形验证码校验标记
* @author 任文超
* @version 1.0.0
* @since 2017-11-07
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CaptchaFineteValidator {
}
...@@ -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)) {
......
...@@ -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 (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;
...@@ -81,7 +82,7 @@ public class CaptchaValidateAdvisor { ...@@ -81,7 +82,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();
} }
......
package cn.quantgroup.xyqb.aspect.limit;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.session.SessionStruct;
import cn.quantgroup.xyqb.session.XyqbSessionContextHolder;
import com.alibaba.fastjson.JSONObject;
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.*;
/**
* 免密访问校验切面
*
* @author 任文超
* @version 1.0.0
* @since 2017-11-21
*/
@Aspect
@Component
public class PasswordFreeAccessValidatorValidateAdvisor {
private static final Logger LOGGER = LoggerFactory.getLogger(PasswordFreeAccessValidatorValidateAdvisor.class);
private static final String PHONE_NO = "phoneNo";
private static final String USER_ID = "userId";
@Autowired
@Qualifier("stringRedisTemplate")
private RedisTemplate<String, String> redisTemplate;
/**
* 免密访问校验切面
*/
@Pointcut("@annotation(cn.quantgroup.xyqb.aspect.limit.PasswordFreeAccessValidator)")
private void passwordFreeAccess() {}
/**
* 执行免密访问校验
*
* @throws Throwable
*/
@Around("passwordFreeAccess()")
private Object checkToken(ProceedingJoinPoint pjp) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
boolean valid = tokenValid(request) || ipValid(request);
if (valid) {
return pjp.proceed();
}
return JsonResult.buildErrorStateResult("拒绝访问", "");
}
/**
* 校验免密访问
* 规则:token 与 身份标记(phoneNo、userId匹配)
* @return True or False
*/
private boolean tokenValid(HttpServletRequest request) {
Objects.requireNonNull(request, "无效请求");
Set<String> paramKeys = request.getParameterMap().keySet();
if(!paramKeys.contains(PHONE_NO) && !paramKeys.contains(USER_ID)){
LOGGER.info("非法请求 - 缺少参数, paramKeys={}, clientIp={}", paramKeys, request.getRemoteAddr());
return false;
}
// 当前请求的phoneNo/userId
String phoneNo = request.getParameter(PHONE_NO);
String userId = request.getParameter(USER_ID);
if(StringUtils.isBlank(phoneNo) && StringUtils.isBlank(userId)){
LOGGER.info("非法请求 - 缺少参数, phoneNo={}, userId={}, clientIp={}", phoneNo, userId, request.getRemoteAddr());
return false;
}
// 当前请求的Token
String token = request.getHeader(Constants.X_AUTH_TOKEN);
if (Objects.isNull(token) || token.length() != 36) {
LOGGER.info("非法请求 - 无效token, token={}, phoneNo={}, userId={}, clientIp={}", token, phoneNo, userId, request.getRemoteAddr());
return false;
}
// 当前session
SessionStruct session = XyqbSessionContextHolder.getXSessionFromRedis(token);
if (Objects.isNull(session) || Objects.isNull(session.getValues()) || Objects.isNull(session.getValues().getUser())){
LOGGER.info("非法请求 - 未登录, token={}, phoneNo={}, userId={}, clientIp={}", token, phoneNo, userId, request.getRemoteAddr());
return false;
}
// 当前用户
User user = session.getValues().getUser();
if(Objects.isNull(user.getId()) && StringUtils.isBlank(user.getPhoneNo())){
LOGGER.info("非法请求 - 未登录, token={}, phoneNo={}, userId={}, clientIp={}", token, phoneNo, userId, request.getRemoteAddr());
return false;
}
// 校对用户信息是否匹配
boolean valid = (Objects.nonNull(user.getId()) && Objects.equals(userId, user.getId().toString()));
valid = valid || (StringUtils.isNotBlank(phoneNo) && Objects.equals(phoneNo, user.getPhoneNo()));
if(!valid) {
LOGGER.info("非法请求 - 身份不匹配, token={}, phoneNo=({},{}), userId=({},{}), clientIp={}", token, phoneNo, user.getPhoneNo(), userId, user.getId(), request.getRemoteAddr());
}
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;
}
}
...@@ -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;
}
} }
package cn.quantgroup.xyqb.aspect.lock;
import java.lang.annotation.*;
/**
* 密码错误限次的校验标记
* @author 任文超
* @version 1.0.0
* @since 2017-11-23
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PasswordFineteValidator {
}
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() {
......
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.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.*;
...@@ -520,9 +520,9 @@ public class InnerController implements IBaseController { ...@@ -520,9 +520,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());
...@@ -574,9 +574,9 @@ public class InnerController implements IBaseController { ...@@ -574,9 +574,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();
......
...@@ -240,12 +240,12 @@ public class SmsController implements IBaseController { ...@@ -240,12 +240,12 @@ public class SmsController implements IBaseController {
LOGGER.info("您手机号已经达到获取今天短信验证码上限:phoneNo:{},deviceId:{},ip:{}",phoneNo,deviceId,getIp()); LOGGER.info("您手机号已经达到获取今天短信验证码上限:phoneNo:{},deviceId:{},ip:{}",phoneNo,deviceId,getIp());
return JsonResult.buildErrorStateResult("今天已获取20次短信验证码,请使用语音验证码或明天再试", null); return JsonResult.buildErrorStateResult("今天已获取20次短信验证码,请使用语音验证码或明天再试", null);
} }
String verificationIPCountKey = getIp(); String clientIp = getIp();
// Todo - 运维解决真实IP获取问题后,打开这段代码,实现按IP限制短信验证码获取量 // Todo - 运维解决真实IP获取问题后,打开这段代码,实现按IP限制短信验证码获取量
// Todo - 另:当前的计数器计数方式为乐观累加,而且还是提前计数,会导致边界值问题,即临界次数会提前一次记满,并且在后续请求到达时计数器会继续计数 // Todo - 另:当前的计数器计数方式为乐观累加,而且还是提前计数,会导致边界值问题,即临界次数会提前一次记满,并且在后续请求到达时计数器会继续计数
/* /*
if (!StringUtils.isEmpty(verificationIPCountKey)) { if (!StringUtils.isEmpty(clientIp)) {
verificationIPCountKey=Constants.REDIS_SMS_IP_COUNT+verificationIPCountKey; String verificationIPCountKey = Constants.REDIS_SMS_IP_COUNT+clientIp;
Long getIPVerificationCount = redisTemplate.opsForHash().increment(verificationIPCountKey, Constants.REDIS_SMS_IP_COUNT, 1); Long getIPVerificationCount = redisTemplate.opsForHash().increment(verificationIPCountKey, Constants.REDIS_SMS_IP_COUNT, 1);
if (getIPVerificationCount > IP_MAX_PER_DAY) { if (getIPVerificationCount > IP_MAX_PER_DAY) {
return JsonResult.buildErrorStateResult("您当前ip已经达到获取今天验证码上限", null); return JsonResult.buildErrorStateResult("您当前ip已经达到获取今天验证码上限", null);
...@@ -277,7 +277,7 @@ public class SmsController implements IBaseController { ...@@ -277,7 +277,7 @@ public class SmsController implements IBaseController {
smsService.getSmsSender().sendMsg(message); smsService.getSmsSender().sendMsg(message);
redisTemplate.opsForValue().set(key, uniqueId + ":" + randomCode, EXPIRE_MINUTES, TimeUnit.MINUTES); redisTemplate.opsForValue().set(key, uniqueId + ":" + randomCode, EXPIRE_MINUTES, TimeUnit.MINUTES);
deleteRetSendCode(phoneNo);//删除用户重置密码,多次错误逻辑 deleteRetSendCode(phoneNo);//删除用户重置密码,多次错误逻辑
if(isApp && needImageVlidate(verificationIPCountKey,deviceId,phoneNo)){ if(isApp && needImageVlidate(clientIp,deviceId,phoneNo)){
return JsonResult.buildSuccessResult("发送成功", uniqueId,0003L); return JsonResult.buildSuccessResult("发送成功", uniqueId,0003L);
} }
LOGGER.info("sendVerificationCode2New获取短信成功:phone:{},deviceId:{},ip:{}",phoneNo,deviceId,getIp()); LOGGER.info("sendVerificationCode2New获取短信成功:phone:{},deviceId:{},ip:{}",phoneNo,deviceId,getIp());
...@@ -299,9 +299,9 @@ public class SmsController implements IBaseController { ...@@ -299,9 +299,9 @@ public class SmsController implements IBaseController {
if (getVerificationCount > PHONE_VOICE_MAX_PER_DAY) { if (getVerificationCount > PHONE_VOICE_MAX_PER_DAY) {
return JsonResult.buildErrorStateResult("今天已获取5次语音验证码,请使用短信验证码或明天再试", null); return JsonResult.buildErrorStateResult("今天已获取5次语音验证码,请使用短信验证码或明天再试", null);
} }
String verificationIPCountKey = getIp(); String clientIp = getIp();
/* if (!StringUtils.isEmpty(verificationIPCountKey)) { /* if (!StringUtils.isEmpty(clientIp)) {
verificationIPCountKey=Constants.REDIS_VOICE_IP_COUNT+verificationIPCountKey; String verificationIPCountKey = Constants.REDIS_VOICE_IP_COUNT+clientIp;
Long getIPVerificationCount = redisTemplate.opsForHash().increment(verificationIPCountKey, Constants.REDIS_VOICE_IP_COUNT, 1); Long getIPVerificationCount = redisTemplate.opsForHash().increment(verificationIPCountKey, Constants.REDIS_VOICE_IP_COUNT, 1);
if (getIPVerificationCount > IP_MAX_PER_DAY) { if (getIPVerificationCount > IP_MAX_PER_DAY) {
return JsonResult.buildErrorStateResult("您当前ip已经达到获取今天语音验证码上限", null); return JsonResult.buildErrorStateResult("您当前ip已经达到获取今天语音验证码上限", null);
...@@ -333,7 +333,7 @@ public class SmsController implements IBaseController { ...@@ -333,7 +333,7 @@ public class SmsController implements IBaseController {
smsService.getSmsSender().sendMsg(message); smsService.getSmsSender().sendMsg(message);
redisTemplate.opsForValue().set(key, uniqueId + ":" + randomCode, EXPIRE_MINUTES, TimeUnit.MINUTES); redisTemplate.opsForValue().set(key, uniqueId + ":" + randomCode, EXPIRE_MINUTES, TimeUnit.MINUTES);
deleteRetSendCode(phoneNo);//删除用户重置密码,多次错误逻辑 deleteRetSendCode(phoneNo);//删除用户重置密码,多次错误逻辑
if(needImageVlidate(verificationIPCountKey,deviceId,phoneNo)){ if(needImageVlidate(clientIp,deviceId,phoneNo)){
return JsonResult.buildSuccessResult("发送成功", uniqueId,0003L); return JsonResult.buildSuccessResult("发送成功", uniqueId,0003L);
} }
......
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);
}
}
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.CaptchaFiniteValidator;
import cn.quantgroup.xyqb.aspect.lock.PasswordFineteValidator; import cn.quantgroup.xyqb.aspect.lock.PasswordErrorFiniteValidator;
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.Merchant; import cn.quantgroup.xyqb.entity.Merchant;
...@@ -83,7 +83,7 @@ public class UserController implements IBaseController { ...@@ -83,7 +83,7 @@ public class UserController implements IBaseController {
public JsonResult test() { public JsonResult test() {
HttpServletRequest request = getRequest(); HttpServletRequest request = getRequest();
String remoteAddr = request.getRemoteAddr(); String remoteAddr = request.getRemoteAddr();
String xRealIp = request.getHeader("x-real-ip"); String xRealIp = IPUtil.getRemoteIP(request);
String xOriginalClientIp = request.getHeader("x-original-client-ip"); String xOriginalClientIp = request.getHeader("x-original-client-ip");
LOGGER.info("Test ips:[client={}, old={}, new={}]", remoteAddr, xRealIp, xOriginalClientIp); LOGGER.info("Test ips:[client={}, old={}, new={}]", remoteAddr, xRealIp, xOriginalClientIp);
return JsonResult.buildSuccessResult("", getCurrentUserFromRedis()); return JsonResult.buildSuccessResult("", getCurrentUserFromRedis());
...@@ -148,7 +148,7 @@ public class UserController implements IBaseController { ...@@ -148,7 +148,7 @@ public class UserController implements IBaseController {
* @param dimension * @param dimension
* @return * @return
*/ */
@CaptchaFineteValidator @CaptchaFiniteValidator
@RequestMapping("/loginV1") @RequestMapping("/loginV1")
public JsonResult loginV1( public JsonResult loginV1(
@RequestParam(required = false, defaultValue = "1") Long channelId, String appChannel, @RequestParam(required = false, defaultValue = "1") Long channelId, String appChannel,
...@@ -175,7 +175,6 @@ public class UserController implements IBaseController { ...@@ -175,7 +175,6 @@ public class UserController implements IBaseController {
* @param request * @param request
* @return * @return
*/ */
// Todo @OneTimeTokenValidator
@RequestMapping("/login/fastV1") @RequestMapping("/login/fastV1")
public JsonResult loginFastV1( public JsonResult loginFastV1(
@RequestParam(required = false, defaultValue = "1") Long channelId, String appChannel, @RequestParam(required = false, defaultValue = "1") Long channelId, String appChannel,
...@@ -188,7 +187,7 @@ public class UserController implements IBaseController { ...@@ -188,7 +187,7 @@ public class UserController implements IBaseController {
} }
@LogHttpCaller @LogHttpCaller
@PasswordFineteValidator @PasswordErrorFiniteValidator
@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,
...@@ -532,7 +531,7 @@ public class UserController implements IBaseController { ...@@ -532,7 +531,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); 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));
} }
......
...@@ -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.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 = {"192.168.3.", "192.168.4.", "172.16.", "172.20.", "172.30."};
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)) {
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;
} }
} }
...@@ -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