SpringCloud 使用Zuul防止xss攻擊和sql注入
解決方法:使用string的本地方法 將特殊符號使用replaceAll方法替換掉,以防止xss攻擊
導入zuul的jar包
<!--zuul-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.0.8.RELEASE</version>
</dependency>
編寫一個過濾器SqLinjectionFilter,繼承ZuulFilter
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.*;
@Component
@Slf4j
@RefreshScope
@Deprecated
public class XssFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String contentType = request.getContentType();
if (StringUtils.isBlank(contentType)) {
return null;
} else if (StringUtils.equals(contentType, "application/x-www-form-urlencoded")
|| StringUtils.equals(contentType, "application/x-www-form-urlencoded;charset=UTF-8")) {
Map<String, String[]> parameterMap = request.getParameterMap();
Iterator it_d = parameterMap.entrySet().iterator();
while (it_d.hasNext()) {
Map.Entry<String, String[]> entry_d = (Map.Entry) it_d.next();
String key = entry_d.getKey();
String[] value = entry_d.getValue();
if (value != null) {
List<String> strings = Arrays.asList(value);
for (int i = 0; i < strings.size(); i++) {
strings.set(i, StringEscapeUtils.escapeHtml(strings.get(i)));
strings.set(i, StringEscapeUtils.escapeJavaScript(strings.get(i)));
}
}
parameterMap.put(key, value);
}
String newBody = JSON.toJSONString(parameterMap);
if (newBody.contains("forbid")) {
setUnauthorizedResponse(requestContext);
}
final byte[] reqBodyBytes = newBody.getBytes();
requestContext.setRequest(new HttpServletRequestWrapper(request) {
@Override
public ServletInputStream getInputStream() {
return new ServletInputStreamWrapper(reqBodyBytes);
}
@Override
public int getContentLength() {
return reqBodyBytes.length;
}
@Override
public long getContentLengthLong() {
return reqBodyBytes.length;
}
});
} else if (StringUtils.equals(contentType, "application/json")
|| StringUtils.equals(contentType, "application/json;charset=UTF-8")) {
try {
InputStream in = requestContext.getRequest().getInputStream();
String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
Map<String, Object> parameterMap = cleanXSS(body);
String newBody = JSON.toJSONString(parameterMap);
if (newBody.contains("forAlone")) {
setUnauthorizedResponse(requestContext);
}
final byte[] reqBodyBytes = newBody.getBytes();
requestContext.setRequest(new HttpServletRequestWrapper(request) {
@Override
public ServletInputStream getInputStream() {
return new ServletInputStreamWrapper(reqBodyBytes);
}
@Override
public int getContentLength() {
return reqBodyBytes.length;
}
@Override
public long getContentLengthLong() {
return reqBodyBytes.length;
}
});
} catch (IOException e) {
log.error("xss過濾器讀取參數異常", e);
}
}
try {
String s = StreamUtils.copyToString(requestContext.getRequest().getInputStream(), Charset.forName("UTF-8"));
System.out.println(s);
} catch (IOException e) {
log.error("xss過濾器讀取參數異常", e);
}
return null;
}
private Map<String, Object> cleanXSS(String value) {
value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
value = value.replaceAll("'", "& #39;");
value = value.replaceAll("eval\\((.*)\\)", "");
value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
value = value.replaceAll("script", "");
value = value.replaceAll("[*]", "[" + "*]");
value = value.replaceAll("[+]", "[" + "+]");
value = value.replaceAll("[?]", "[" + "?]");
String badStr = "'|and|exec|execute|insert|select|delete|update|count|drop|%|chr|mid|master|truncate|" +
"char|declare|sitename|net user|xp_cmdshell|;|or|+|,|like'|and|exec|execute|insert|create|drop|" +
"table|from|grant|use|group_concat|column_name|" +
"information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|" +
"chr|mid|master|truncate|char|declare|or|;|--|,|like|//|/|%|#";
JSONObject json = JSON.parseObject(value);
String[] badStrs = badStr.split("\\|");
Map<String, Object> map = json;
Map<String, Object> mapJson = new HashMap<>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
String value1 = entry.getValue().toString();
for (String bad : badStrs) {
if (value1.equalsIgnoreCase(bad)) {
value1 = "forAlone";
mapJson.put(entry.getKey(), value1);
break;
} else {
mapJson.put(entry.getKey(), entry.getValue());
}
}
}
return mapJson;
}
private void setUnauthorizedResponse(RequestContext requestContext) {
requestContext.setResponseBody(JSON.toJSONString(ResultBean.errorResult(500, "您填寫的值存在sql注入問題")));
}
}