基于Validate排序字段防SQL注入
一、定义排序基类
public interface BaseSortModel { String getSort();
@ApiModelProperty(hidden = true)
default String getSortField() {
if (StringUtils.isNotBlank(getSort()) && getSort().contains("-")) {
return getSort().split("-")[0];
}
return null;
}
@ApiModelProperty(hidden = true)
default String getSortType() {
if (StringUtils.isNotBlank(getSort()) && getSort().contains("-")) {
return getSort().split("-")[1];
}
return null;
}
}
二、定义校验注解
@Target({ FIELD, PARAMETER})@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {Sort.SortValidator.class})
public @interface Sort {
String message() default "不支持的排序字段";
Class<?>[] FieldOfClass() default {};
String[] fields() default {};
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
三、定义校验器
@Slf4j
class SortValidator implements ConstraintValidator<Sort, String> {
private static Map<String, Set<String>> supportBeanFields = Maps.newConcurrentMap();
private static List<String> supportSortTypes = Lists.newArrayList("asc", "ASC", "desc", "DESC");
private Sort sortAnn;
@Override
public void initialize(Sort ann) {
this.sortAnn = ann;
if (ArrayUtils.isNotEmpty(sortAnn.FieldOfClass())) {
for (Class<?> clz : sortAnn.FieldOfClass()) {
Set<String> clzFields = supportBeanFields.get(clz.getName());
if (Objects.nonNull(clzFields)) {
continue;
}
Field[] fields = clz.getDeclaredFields();
if (ArrayUtils.isEmpty(fields)) {
supportBeanFields.putIfAbsent(clz.getName(), Sets.newHashSet());
continue;
}
clzFields = Sets.newHashSetWithExpectedSize(fields.length * 2);
for (Field field : fields) {
field.setAccessible(true);
clzFields.add(field.getName());
clzFields.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, field.getName()));
}
supportBeanFields.putIfAbsent(clz.getName(), clzFields);
}
}
}
/**
* 校验排序字段
*
* @param value 值
* @param context 校验器上下文
* @return 是否校验成功
*/
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (StringUtils.isEmpty(value)) {
return true;
}
if (!SQLFilter.checkSqlInject(value)) {
return false;
}
String[] split = value.split("-");
if (split.length != 2) {
log.error("排序字段格式格式有误,比如[字段名-asc]");
return false;
}
String sortField = split[0];
String sortType = split[1];
if (ArrayUtils.isEmpty(sortAnn.fields()) && ArrayUtils.isEmpty(sortAnn.FieldOfClass())) {
log.error("排序字段必须限定枚举值,请对@sort的fields或者fieldOfClass赋值)");
return false;
}
boolean isSupport = false;
if (ArrayUtils.isNotEmpty(sortAnn.fields())) {
if (ArrayUtils.contains(sortAnn.fields(), sortField)) {
isSupport = true;
}
}
if (ArrayUtils.isNotEmpty(sortAnn.FieldOfClass())) {
for (Class<?> clz : sortAnn.FieldOfClass()) {
Set<String> supportFields = supportBeanFields.get(clz.getName());
if (supportFields.contains(sortField)) {
isSupport = true;
break;
}
}
}
if (!supportSortTypes.contains(sortType)) {
log.error("不支持的排序类型, 仅支持[asc、desc]");
return false;
}
return isSupport;
}
}
四、SQL注入校验工具类
@Slf4j
public class SQLFilter {
public static String[] illegalKeywords = {""", """, ";", "\", "master", "truncate", "insert", "select", "delete", "update", "declare", "alert", "drop"};
/**
* SQL注入校验
*
* @param param 待验证的字符串
*/
public static String sqlInject(String param){
if(StringUtils.isBlank(param)){
return param;
}
String lowerParam = param.toLowerCase();
for(String illegalKeyword : illegalKeywords){
if(lowerParam.contains(illegalKeyword)){
throw new ParameterException(ReturnCode.PARAM_ERROR,
"参数:[" + param + "],含非法关键词[", ", ;, \, master, truncate, insert, select, delete, update, declare, alert, drop]");
}
}
return param;
}
/**
* SQL注入校验
*
* @param param 待验证的字符串
*/
public static boolean checkSqlInject(String param){
if(StringUtils.isBlank(param)){
return true;
}
String lowerParam = param.toLowerCase();
for(String illegalKeyword : illegalKeywords){
if(lowerParam.contains(illegalKeyword)){
return false;
}
}
return true;
}
}
以上是 基于Validate排序字段防SQL注入 的全部内容, 来源链接: utcz.com/z/517241.html