spring gateway 集成sql注入过滤
一、创建过滤器
创建一个过滤器实现于GlobalFilter接口。
获取当前url相关信息
//获取URI,以及头部
ServerHttpRequest serverHttpRequest = exchange.getRequest();
HttpMethod method = serverHttpRequest.getMethod();
String contentType = serverHttpRequest.getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
URI uri = exchange.getRequest().getURI();
//1.动态刷新 sql注入的过滤的路径
String path = serverHttpRequest.getURI().getRawPath();
String[] matchUrls = this.getSqlinjectionHttpUrls();
if (AuthUtils.isMatchPath(path, matchUrls)) {
logger.error("请求【{}】在sql注入过滤白名单中,直接放行", path);
return chain.filter(exchange);
}
二、get、post方法注入检测
分开Get和Post方法进行检测
1)get方法检测
如果为Get方法,代码如下
if (method == HttpMethod.GET) {
String rawQuery = uri.getRawQuery();
if (StringUtils.isBlank(rawQuery)) {
return chain.filter(exchange);
}
logger.debug("请求参数为:{}", rawQuery);
// 执行sql注入校验清理
boolean chkRet = false;
try {
chkRet = sqlInjectionRuleUtils.getRequestSqlKeyWordsCheck(rawQuery);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//如果存在sql注入,直接拦截请求
if (chkRet) {
logger.error("请求【" + uri.getRawPath() + uri.getRawQuery() + "】参数中包含不允许sql的关键词, 请求拒绝");
return setUnauthorizedResponse(exchange);
}
//透传参数,不对参数做任何处理
return chain.filter(exchange);
}
get方法注入检测实现方法getRequestSqlKeyWordsCheck如下
public static boolean getRequestSqlKeyWordsCheck(String value) throws UnsupportedEncodingException {
//参数需要url编码
//这里需要将参数转换为小写来处理
//不改变原值
//value示例 order=asc&pageNum=1&pageSize=100&parentId=0
String lowerValue = URLDecoder.decode(value, "UTF-8").toLowerCase();
//获取到请求中所有参数值-取每个key=value组合第一个等号后面的值
return Stream.of(lowerValue.split("\\&"))
.map(kp -> kp.substring(kp.indexOf("=") + 1))
.parallel()
.anyMatch(param -> {
if (sqlPattern.matcher(param).find()) {
logger.error("参数中包含不允许sql的关键词");
return true;
}
return false;
});
}
2)post方法检测
如果为Post方法:
//post请求时,如果是文件上传之类的请求,不修改请求消息体
else if (postFlag) {
return DataBufferUtils.join(serverHttpRequest.getBody()).flatMap(d -> Mono.just(Optional.of(d))).defaultIfEmpty(
Optional.empty())
.flatMap(optional -> {
// 取出body中的参数
String bodyString = "";
if (optional.isPresent()) {
byte[] oldBytes = new byte[optional.get().readableByteCount()];
optional.get().read(oldBytes);
bodyString = new String(oldBytes, StandardCharsets.UTF_8);
}
HttpHeaders httpHeaders = serverHttpRequest.getHeaders();
logger.debug("{} - [{}] 请求参数:{}", method, uri.getPath(), bodyString);
boolean chkRet = false;
if (MediaType.APPLICATION_JSON_VALUE.equals(contentType)) {
//如果MediaType是json才执行json方式验证
chkRet = sqlInjectionRuleUtils.postRequestSqlKeyWordsCheck(bodyString);
} else {
//form表单方式,需要走get请求
try {
chkRet = sqlInjectionRuleUtils.getRequestSqlKeyWordsCheck(bodyString);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
// 如果存在sql注入,直接拦截请求
if (chkRet