All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.gitee.easyopen.ApiValidator Maven / Gradle / Ivy
package com.gitee.easyopen;
import com.gitee.easyopen.exception.BusinessParamException;
import com.gitee.easyopen.message.ErrorFactory;
import com.gitee.easyopen.message.Errors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidatorFactory;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 负责校验,校验工作都在这里
*
* @author tanghc
*
*/
@Slf4j
public class ApiValidator implements Validator {
private final List SYSTEM_PACKAGE_LIST = Arrays.asList("java.lang", "java.math", "java.util", "sun.util");
private javax.validation.Validator validator;
public ApiValidator() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Override
public void validate(ApiParam param) {
if (ApiContext.getApiConfig().isIgnoreValidate() || param.fatchIgnoreValidate()) {
log.debug("忽略所有验证(ignoreValidate=true), name:{}, version:{}", param.fatchName(), param.fatchVersion());
return;
}
Assert.notNull(ApiContext.getApiConfig().getAppSecretManager(), "appSecretManager未初始化");
if (param.fatchIgnoreSign()) {
log.debug("忽略签名验证, name:{}, version:{}", param.fatchName(), param.fatchVersion());
} else {
// 需要验证签名
checkAppKey(param);
checkSign(param);
}
checkUploadFile(param);
checkTimeout(param);
}
/**
* 校验上传文件内容
* @param param
*/
protected void checkUploadFile(ApiParam param) {
UploadContext uploadContext = ApiContext.getUploadContext();
if(uploadContext != null) {
try {
List files = uploadContext.getAllFile();
for (MultipartFile file : files) {
// 客户端传来的文件md5
String clientMd5 = param.getString(file.getName());
if(clientMd5 != null) {
String fileMd5 = DigestUtils.md5Hex(file.getBytes());
if(!clientMd5.equals(fileMd5)) {
throw Errors.ERROR_UPLOAD_FILE.getException();
}
}
}
}catch (IOException e) {
log.error("验证上传文件MD5错误", e);
throw Errors.ERROR_UPLOAD_FILE.getException();
}
}
}
protected void checkTimeout(ApiParam param) {
int timeoutSeconds = ApiContext.getApiConfig().getTimeoutSeconds();
// 如果设置为0,表示不校验
if(timeoutSeconds == 0) {
return;
}
if (timeoutSeconds < 0) {
throw new IllegalArgumentException("服务端timeoutSeconds设置错误");
}
String requestTime = param.fatchTimestamp();
try {
Date requestDate = new SimpleDateFormat(ParamNames.TIMESTAMP_PATTERN).parse(requestTime);
long requestMilliseconds = requestDate.getTime();
if (System.currentTimeMillis() - requestMilliseconds > timeoutSeconds * 1000) {
throw Errors.TIMEOUT.getException(param.fatchNameVersion(), timeoutSeconds);
}
} catch (ParseException e) {
throw Errors.TIME_INVALID.getException(param.fatchNameVersion());
}
}
protected void checkAppKey(ApiParam param) {
Assert.notNull(ApiContext.getApiConfig().getAppSecretManager(), "appSecretManager未初始化");
if (StringUtils.isEmpty(param.fatchAppKey())) {
throw Errors.NO_APP_ID.getException(param.fatchNameVersion(), ParamNames.APP_KEY_NAME);
}
boolean isTrueAppKey = ApiContext.getApiConfig().getAppSecretManager().isValidAppKey(param.fatchAppKey());
if (!isTrueAppKey) {
throw Errors.ERROR_APP_ID.getException(param.fatchNameVersion(), ParamNames.APP_KEY_NAME);
}
}
protected void checkSign(ApiParam param) {
if (StringUtils.isEmpty(param.fatchSign())) {
throw Errors.NO_SIGN_PARAM.getException(param.fatchNameVersion(), ParamNames.SIGN_NAME);
}
String secret = ApiContext.getApiConfig().getAppSecretManager().getSecret(param.fatchAppKey());
Signer signer = ApiContext.getApiConfig().getSigner();
boolean isRightSign = signer.isRightSign(param, secret, param.fatchSignMethod());
// 错误的sign
if(!isRightSign) {
throw Errors.ERROR_SIGN.getException(param.fatchNameVersion());
}
}
@Override
public void validateBusiParam(Object obj) {
if(obj == null) {
return;
}
// 先校验属性对象
List fields = listObjectField(obj);
if (!fields.isEmpty()) {
fields.forEach(this::validateBusiParam);
}
Set> set = validator.validate(obj);
if (CollectionUtils.isNotEmpty(set)) {
ConstraintViolation oneError = set.iterator().next();
String errorMsg = oneError.getMessage();
throw this.getValidateBusiParamException(errorMsg);
}
}
private List listObjectField(Object object) {
List ret = new ArrayList<>();
ReflectionUtils.doWithFields(object.getClass(), field -> {
ReflectionUtils.makeAccessible(field);
ret.add(field.get(object));
}, this::isMatchField);
return ret;
}
/**
* 匹配校验字段。
*
* 1. 不为基本类型;
* 2. 不为java自带的类型;
* 3. 不为枚举
* 4. 不为Map
* @param field field
* @return true,是自定义的
*/
private boolean isMatchField(Field field) {
Class> fieldType = field.getType();
if (fieldType.isPrimitive()) {
return false;
}
if (Map.class.isAssignableFrom(fieldType)) {
return false;
}
Class> declaringClass = field.getDeclaringClass();
boolean isSame = declaringClass == fieldType;
boolean isAssignableFrom = declaringClass.isAssignableFrom(fieldType)
|| fieldType.isAssignableFrom(declaringClass);
// 如果是相同类,或者有继承关系不校验。
if (isSame || isAssignableFrom) {
return false;
}
Package aPackage = fieldType.getPackage();
if (aPackage == null) {
return false;
}
String packageName = aPackage.getName();
for (String prefix : SYSTEM_PACKAGE_LIST) {
if (packageName.startsWith(prefix)) {
return false;
}
}
return true;
}
private RuntimeException getValidateBusiParamException(String errorMsg) {
String code = Errors.BUSI_PARAM_ERROR.getCode();
String[] msgToken = errorMsg.split("=");
String msg = msgToken[0];
if (msg.startsWith("{") && msg.endsWith("}")) {
String module = msg.substring(1, msg.length() - 1);
Object[] params = this.buildParams(msgToken);
String error = ErrorFactory.getErrorMessage(module, ApiContext.getLocal(), params);
return new BusinessParamException(error, code);
} else {
return new BusinessParamException(errorMsg, code);
}
}
private Object[] buildParams(String[] msgToken) {
if (msgToken.length == 2) {
return msgToken[1].split(",");
} else {
return new Object[0];
}
}
public javax.validation.Validator getValidator() {
return validator;
}
public void setValidator(javax.validation.Validator validator) {
this.validator = validator;
}
}