REM:
1. 增加接口超时检测相关配置和功能
2. 更新接口请求参数校验组类名
3. 增加单元测试Base类返回协议头校验功能
4. 增加登录、注销功能单元测试
This commit is contained in:
HuangXin 2020-07-27 14:14:35 +08:00
parent f3369d8cee
commit 4216d24a12
11 changed files with 103 additions and 22 deletions

View File

@ -58,6 +58,7 @@ dispose.debug-model=true
dispose.check-protocol-timeout=false dispose.check-protocol-timeout=false
dispose.check-request-token=true dispose.check-request-token=true
dispose.split_char=, dispose.split_char=,
dispose.request-timeout-second=5
# 迪普设备配置 # 迪普设备配置
# 发送超时时间(ms) # 发送超时时间(ms)

View File

@ -14,7 +14,7 @@ public class AuthConfigValue {
/** /**
* The constant TOKEN_EXPIRED_TIME_MS. * The constant TOKEN_EXPIRED_TIME_MS.
*/ */
public static long TOKEN_EXPIRED_TIME_MS = 30 * 60 * 1000; public static volatile long TOKEN_EXPIRED_TIME_MS = 30 * 60 * 1000;
/** /**
* The constant MYSQL_REGEX. * The constant MYSQL_REGEX.

View File

@ -0,0 +1,19 @@
package com.dispose.common;
/**
* The type Dispose config value.
*
* @author <huangxin@cmhi.chinamoblie.com>
*/
public class DisposeConfigValue {
/**
* The constant CHECK_PROTO_REQUEST_TIMEOUT.
*/
public static volatile boolean CHECK_PROTO_REQUEST_TIMEOUT = false;
/**
* The constant REQUEST_TIMEOUT_MS.
*/
public static volatile long REQUEST_TIMEOUT_MS = 5 * 1000;
}

View File

@ -53,4 +53,8 @@ public enum ProtoCryptoType {
public String getReadme() { public String getReadme() {
return this.readme; return this.readme;
} }
public static boolean verifyCryptoValuable(int code) {
return code >= CRYPTO_NONE.getCode() && code <= CRYPTO_DES.getCode();
}
} }

View File

@ -27,4 +27,9 @@ public class DisposeConfigure {
* The Split char. * The Split char.
*/ */
private String splitChar; private String splitChar;
/**
* The Request timeout second.
*/
private String requestTimeoutSecond;
} }

View File

@ -55,7 +55,7 @@ public class AuthController {
@ResponseBody @ResponseBody
@ApiOperation("登录") @ApiOperation("登录")
public ProtocolRespDTO<? extends BaseRespStatus> userLogin( public ProtocolRespDTO<? extends BaseRespStatus> userLogin(
@Validated(ValidGroups.LoginReq.class) @Validated(ValidGroups.LoginReqValid.class)
@RequestBody ProtocolReqDTO<LoginReq> mr) @RequestBody ProtocolReqDTO<LoginReq> mr)
throws NoSuchAlgorithmException { throws NoSuchAlgorithmException {
@ -95,7 +95,7 @@ public class AuthController {
@PostMapping("/logout") @PostMapping("/logout")
@ResponseBody @ResponseBody
@ApiOperation("注销") @ApiOperation("注销")
public ProtocolRespDTO<? extends BaseRespStatus> userLogout(@Validated(ValidGroups.LogoutReq.class) public ProtocolRespDTO<? extends BaseRespStatus> userLogout(@Validated(ValidGroups.LogoutReqValid.class)
@RequestBody ProtocolReqDTO<LoginReq> mr, @RequestBody ProtocolReqDTO<LoginReq> mr,
@RequestHeader HttpHeaders headers) { @RequestHeader HttpHeaders headers) {
// 注销用户登录 // 注销用户登录

View File

@ -35,13 +35,13 @@ public class LoginReq {
/** /**
* The Password. * The Password.
*/ */
@NotBlank(message = "password 密码不能为空", groups = ValidGroups.LoginReq.class) @NotBlank(message = "password 密码不能为空", groups = ValidGroups.LoginReqValid.class)
@Length(min = 64, max = 64, @Length(min = 64, max = 64,
message = "password 密码长度必须为SHA256编码后的长度", message = "password 密码长度必须为SHA256编码后的长度",
groups = ValidGroups.LoginReq.class) groups = ValidGroups.LoginReqValid.class)
@Pattern(regexp = AuthConfigValue.MYSQL_REGEX_CHARS, @Pattern(regexp = AuthConfigValue.MYSQL_REGEX_CHARS,
flags = Pattern.Flag.CASE_INSENSITIVE, flags = Pattern.Flag.CASE_INSENSITIVE,
message = "password 密码存在非法字符串", message = "password 密码存在非法字符串",
groups = ValidGroups.LoginReq.class) groups = ValidGroups.LoginReqValid.class)
private String password; private String password;
} }

View File

@ -26,8 +26,8 @@ public class BaseProtocolDTO<T> {
* 当前协议版本号 * 当前协议版本号
*/ */
@ApiModelProperty(value = "协议版本号", required = true, example = "1") @ApiModelProperty(value = "协议版本号", required = true, example = "1")
@NotNull(message = "ver 字段不能为空", groups = ValidGroups.ProtocolCommon.class) @NotNull(message = "ver 字段不能为空", groups = ValidGroups.ProtocolCommonValid.class)
@Range(min = 3, max = 9999, message = "ver 字段最小值为 3", groups = ValidGroups.ProtocolCommon.class) @Range(min = 3, max = 9999, message = "ver 字段最小值为 3", groups = ValidGroups.ProtocolCommonValid.class)
private Integer ver; private Integer ver;
/** /**
@ -39,20 +39,20 @@ public class BaseProtocolDTO<T> {
"2采用AES加密后的base64编码格式\n", required = true, "2采用AES加密后的base64编码格式\n", required = true,
allowableValues = "0, 1, 2", allowableValues = "0, 1, 2",
example = "0") example = "0")
@NotNull(message = "cryptoType 字段不能为空", groups = ValidGroups.ProtocolCommon.class) @NotNull(message = "cryptoType 字段不能为空", groups = ValidGroups.ProtocolCommonValid.class)
@Range(min = 0, max = 2, @Range(min = 0, max = 2,
message = "cryptoType 字段取值为 [0, 2]" message = "cryptoType 字段取值为 [0, 2]"
, groups = ValidGroups.ProtocolCommon.class) , groups = ValidGroups.ProtocolCommonValid.class)
private Integer cryptoType; private Integer cryptoType;
/** /**
* 当前UTC时间戳(ms) * 当前UTC时间戳(ms)
*/ */
@ApiModelProperty(value = "当前UTC时间戳", required = true, example = "1526625689000") @ApiModelProperty(value = "当前UTC时间戳", required = true, example = "1526625689000")
@NotNull(message = "timeStamp 字段不能为空", groups = ValidGroups.ProtocolCommon.class) @NotNull(message = "timeStamp 字段不能为空", groups = ValidGroups.ProtocolCommonValid.class)
@DecimalMin(value = "1595494343000", @DecimalMin(value = "1595494343000",
message = "timeStamp 字段值不能为过去时间" message = "timeStamp 字段值不能为过去时间"
, groups = ValidGroups.ProtocolCommon.class) , groups = ValidGroups.ProtocolCommonValid.class)
private Long timeStamp; private Long timeStamp;
/** /**

View File

@ -11,7 +11,7 @@ public class ValidGroups {
* *
* @author <huangxin@cmhi.chinamoblie.com> * @author <huangxin@cmhi.chinamoblie.com>
*/ */
public interface ProtocolCommon { public interface ProtocolCommonValid {
} }
/** /**
@ -19,7 +19,7 @@ public class ValidGroups {
* *
* @author <huangxin@cmhi.chinamoblie.com> * @author <huangxin@cmhi.chinamoblie.com>
*/ */
public interface LoginReq extends ProtocolCommon { public interface LoginReqValid extends ProtocolCommonValid {
} }
/** /**
@ -27,6 +27,6 @@ public class ValidGroups {
* *
* @author <huangxin@cmhi.chinamoblie.com> * @author <huangxin@cmhi.chinamoblie.com>
*/ */
public interface LogoutReq extends ProtocolCommon { public interface LogoutReqValid extends ProtocolCommonValid {
} }
} }

View File

@ -1,6 +1,7 @@
package com.dispose.setup; package com.dispose.setup;
import com.dispose.common.AuthConfigValue; import com.dispose.common.AuthConfigValue;
import com.dispose.common.DisposeConfigValue;
import com.dispose.common.DpTechConfigValue; import com.dispose.common.DpTechConfigValue;
import com.dispose.config.AuthConfigure; import com.dispose.config.AuthConfigure;
import com.dispose.config.DisposeConfigure; import com.dispose.config.DisposeConfigure;
@ -59,12 +60,18 @@ public class SystemInitial implements CommandLineRunner {
} catch(Exception ex) { } catch(Exception ex) {
log.error("load SOAP_RECEIVE_TIMEOUT_SECOND configure error: {}", ex.getMessage()); log.error("load SOAP_RECEIVE_TIMEOUT_SECOND configure error: {}", ex.getMessage());
} }
//
// try { try {
// GlobalVar.IS_CHECK_REQUEST_TIMEOUT = Boolean.parseBoolean(disposeConfigure.getCheckProtocolTimeout()); DisposeConfigValue.REQUEST_TIMEOUT_MS = Integer.parseInt(disposeConfigure.getRequestTimeoutSecond()) * 1000;
// } catch(Exception ex) { } catch(Exception ex) {
// log.error("load IS_CHECK_REQUEST_TIMEOUT configure error: {}", ex.getMessage()); log.error("load REQUEST_TIMEOUT_MS configure error: {}", ex.getMessage());
// } }
try {
DisposeConfigValue.CHECK_PROTO_REQUEST_TIMEOUT = Boolean.parseBoolean(disposeConfigure.getCheckProtocolTimeout());
} catch(Exception ex) {
log.error("load CHECK_PROTO_REQUEST_TIMEOUT configure error: {}", ex.getMessage());
}
} }
/** /**

View File

@ -1,6 +1,10 @@
package com.dispose.test.Global; package com.dispose.test.Global;
import com.dispose.common.ConstValue;
import com.dispose.common.DisposeConfigValue;
import com.dispose.common.ErrorCode; import com.dispose.common.ErrorCode;
import com.dispose.common.ProtoCryptoType;
import com.dispose.pojo.dto.protocol.base.ProtocolRespDTO;
import com.dispose.pojo.po.MulReturnType; import com.dispose.pojo.po.MulReturnType;
import com.dispose.service.UserAccountService; import com.dispose.service.UserAccountService;
import lombok.Getter; import lombok.Getter;
@ -14,13 +18,15 @@ import javax.annotation.Resource;
/** /**
* The type Init test environment. * The type Init test environment.
*
* @author <huangxin@cmhi.chinamoblie.com>
*/ */
@Slf4j @Slf4j
@Getter @Getter
@ActiveProfiles("local") @ActiveProfiles("local")
public class InitTestEnvironment { public class InitTestEnvironment {
/** /**
* The connect timeout. * The constant HTTP_CONNECT_TIMEOUT.
*/ */
public static final int HTTP_CONNECT_TIMEOUT = 10000; public static final int HTTP_CONNECT_TIMEOUT = 10000;
/** /**
@ -64,4 +70,43 @@ public class InitTestEnvironment {
Assert.assertNotNull(logToken); Assert.assertNotNull(logToken);
Assert.assertNotEquals(logToken.length(), 0); Assert.assertNotEquals(logToken.length(), 0);
} }
/**
* Verify resp protocol.
*
* @param <T> the type parameter
* @param proObject the pro object
*/
public <T> void verifyRespProtocol(ProtocolRespDTO<T> proObject) {
try {
// 检查协议版本
if (proObject.getVer() < ConstValue.Protocol.VERSION) {
log.error("Protocol version: {} need {}", proObject.getVer(), ConstValue.Protocol.VERSION);
Assert.fail();
}
// 检查请求是否超时
if (DisposeConfigValue.CHECK_PROTO_REQUEST_TIMEOUT) {
Assert.assertFalse(Math.abs(System.currentTimeMillis() - proObject.getTimeStamp())
>= DisposeConfigValue.REQUEST_TIMEOUT_MS);
}
// 检查加密方式
Assert.assertTrue(ProtoCryptoType.verifyCryptoValuable(proObject.getCryptoType()));
} catch (Exception ex) {
log.error("Protocol Exception: {}", ex.getMessage());
Assert.fail();
}
}
/**
* Gets login token.
*
* @return the login token
*/
public String getLoginToken() {
return logToken;
}
} }