sql参数过滤
对网络上普遍的都是直接对关键字进行替换,是实际上mysql关键字不区分大小写,在sql执行中,select、SELECT、Select的效果是一致的。网络上的普遍过滤效果不佳,自己写了一个工具类进行过滤。
逻辑
- 关键字前后有空格才算是有效待过滤的,以防过滤正常的参数
- 通过全部小写进行匹配,匹配后通过获得下标
- 通过下标以及匹配的关键对传入的参数进行下标用空格替换
- 去除前后空格
代码
package com.platform.common.util;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
/**
* describe:过滤参数的sql关键字<br/>
* 关键字前后有空格才算是有效的,若前后没有空格,不认为是需要过滤的关键字
* @author Administrator
* @date 2020/11/17
* @Time 21:02
*/
public class SqlKeyUtil {
private static final String KEY = "exec|insert|select|delete|update|count|%|chr|mid|master|truncate|char|declare";
private static final Set<String> KEYS;
static {
String[] keys = KEY.split("\\|");
KEYS = new HashSet<>(keys.length);
Collections.addAll(KEYS, keys);
}
public static String clean(String value) {
String[] valIndex = value.split("");
String lowValue = value.toLowerCase();
int valueLength = value.length();
for (String keyword : KEYS) {
if (lowValue.contains(keyword)) {
String[] split = lowValue.split(keyword);
int keyLength = keyword.length();
int sumLength = 0;
boolean haveSpace = false;
for (String s: split) {
int t = s.length();
sumLength += t;
int tempLength = sumLength + keyLength;
if (tempLength > valueLength){
break;
}else if (tempLength < valueLength){
if (t > 0){
haveSpace = 32 == value.charAt(t-1) || 32 == value.charAt(tempLength);
}else {
haveSpace = 32 == value.charAt(tempLength);
}
}else if(sumLength + keyLength == valueLength){
haveSpace = 32 == value.charAt(sumLength-1);
}
if (haveSpace){
for (int i = sumLength; i < tempLength; i++) {
valIndex[i] = " ";
}
}
sumLength = tempLength;
}
}
}
return StringUtils.join(valIndex, null).trim();
}
public static void main(String[] args) {
String value = "SELECT1 from SELECT 2 SELECT insert Insert 12345 Select select";
String cleanVal = SqlKeyUtil.clean(value);
System.out.println("过滤前:"+value);
System.out.println("过滤后:"+cleanVal);
}
}