赞
踩
麻烦死了,用正则是不是简单些
public class SQLParamChecker { // 关键字 private static List<String> SPECIAL_WORDS; private static BloomFilter<String> FILTER; static { FILTER = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), 100000, 0.01); SPECIAL_WORDS = ZYFileUtils.readClassPathFile2List("sql_special_key.txt"); // 单词的长短倒序,先判断长的,再判断误的,避免长的包含短的误关 如into in这种,先判断into,再判断in SPECIAL_WORDS.sort(Comparator.comparing(String::length).reversed()); } public static void main(String[] args) { String sql1 = "select Icollect'and(select*from(select+sleep(2))a/**/union/**/select+1)=' select"; String sql2 = "select "; checkExistsIllegalSQL(sql1); checkExistsIllegalSQL(sql2); checkExistsIllegalSQL(sql2); } public static void checkExistsIllegalSQL(String context) { if (ZYStrUtils.isNull(context)) { return; } if (FILTER.mightContain(context)) { return; } // 统一转为小写 String text = context.toLowerCase(); if (text.contains("'")) { throw new IllegalSqlException(); } // 检查是否存在关键字 if (hasSpecialWord(text)) { throw new IllegalSqlException(); } if (context.length() < 30) { // 小于30(经验值)的短参数直接跳过去,用布隆过滤器不知道有没有问题,会有一定的内存溢出风险,比起大量循环判断来说。还是值得一试 FILTER.put(context); } } private static boolean hasSpecialWord(String text) { for (String specialWord : SPECIAL_WORDS) { // 等于关键字无所谓 if (text.length() == specialWord.length()) { return false; } // 找到关键字索引 List<Integer> indexs = findPlaceLocal(text, specialWord); if (indexs.size() == 0) { continue; } for (Integer index : indexs) { // 前置检查 boolean isPreSpecialSymbol; if (index == 0) { // 关键字开头 isPreSpecialSymbol = true; } else { String preLatter = text.substring(index - 1, index); // 前置字母被关键字包裹 isPreSpecialSymbol = isSpecialSymbol(preLatter); } // 后置检查 int beginIndex = index + specialWord.length(); int endIndex = beginIndex + 1; boolean isAfterSpecialSymbol; if (endIndex >= text.length()) { // 关键字结尾 isAfterSpecialSymbol = true; } else { String postLetter = text.substring(beginIndex, endIndex); // 后置字母被关键字包裹 isAfterSpecialSymbol = isSpecialSymbol(postLetter); } // 检测到关键字,并且关键字的前后是非字母相连,判断为sql关键字 (select *这种 xxxselectxx 这种不算 if (isPreSpecialSymbol && isAfterSpecialSymbol) { return true; } } } return false; } private static List<Integer> findPlaceLocal(String text, String word) { int index = 0; List<Integer> placeIndexs = new ArrayList<>(); while (index != -1) { index = ZYStrUtils.indexOf(text, word, index, false); if (index != -1) { placeIndexs.add(index); index = index + word.length(); } } return placeIndexs; } private static boolean isSpecialSymbol(String letter) { char aChar = letter.toCharArray()[0]; char line='_'; // 数字、字母、下划线 boolean isLatter = aChar <= 9 || (aChar >= 97 && aChar <= 122) || aChar == line;; return !isLatter; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。