目录
①:创建Xss请求过滤类XssHttpServletRequestWraper
②:把请求过滤类CustomHttpServletRequestWraper添加到Filter中,注入容器
目录
①:创建Xss请求过滤类XssHttpServletRequestWraper
②:把请求过滤类CustomHttpServletRequestWraper添加到Filter中,注入容器
对于Xss攻击和Sql注入,我们可以通过过滤器来搞定,可根据业务需要排除部分请求
以下是拦截所有加有@SqlInterceptorAnno 注解的请求,进行请求体参数转义处理
①:创建Xss请求过滤类XssHttpServletRequestWraper
此处使用
CustomHttpServletRequestWrapper,主要是过滤接口进行转义字符操作
代码如下:
/**
* HttpServlettFilter的包装类,修改sql like特殊字符
*/
public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {
// 保存request body的数据
private String body;
@SneakyThrows
public CustomHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
InputStream inputStream = null;
try {
inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
} finally {
if (inputStream != null) {
try {
inputStream.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
body = stringBuilder.toString();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return servletInputStream;
}
public String getBody() {
return this.body;
}
// 赋值给body字段
public void setBody(String body) {
this.body = body;
}
}
②:把请求过滤类CustomHttpServletRequestWraper
添加到Filter中,注入容器
@WebFilter(urlPatterns = "/*")
public class SqlFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
CustomHttpServletRequestWrapper sqlWrapper = new CustomHttpServletRequestWrapper(httpRequest);
//继续处理请求
chain.doFilter(sqlWrapper, response);
}
}
③:自定义Sql拦截器处理类
@Component
@Slf4j
public class SqlInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
//方法有无加注解
SqlInterceptorAnno annotation = method.getAnnotation(SqlInterceptorAnno.class);
//1、没有加注解,判断所在类有没有加注解
if( annotation == null ){
System.out.println(method.getName()+"方法无注解");
annotation = method.getDeclaringClass().getAnnotation(SqlInterceptorAnno.class);
if(annotation == null){
System.out.println(method.getName()+"所在类无注解");
return true;
}
System.out.println(method.getName()+"所在类有注解");
}
else {
doSqlExchange(request);
}
}
return true;
}
private void doSqlExchange(HttpServletRequest request) {
try{
if(request instanceof CustomHttpServletRequestWrapper) {
CustomHttpServletRequestWrapper requestWrapper = (CustomHttpServletRequestWrapper)request;
String body = requestWrapper.getBody();
log.info(body);
Map<String,Object> map= JSONUtil.parseObj(body);
Map<String,Object> result=new LinkedHashMap<>();
for(String key:map.keySet()){
Object val=map.get(key);
if (!val.equals(null)){
if(val instanceof String){
String newVal = (String) val;
if(((String) val).contains("_")){
newVal = newVal.replace("_", "\\_");
}
if(((String) val).contains("%")){
newVal = newVal.replace("%", "\\%");
}
result.put(key, newVal);
}
else {
result.put(key,val);
}
}else {
result.put(key, "");
}
}
requestWrapper.setBody(JSONObject.toJSONString(result));
}
}catch (Exception e){
log.warn("fill userInfo to request body Error ", e);
}
}
}
④:自定义拦截器注解
importjava.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*自定义过滤注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METH0D,ElementType.TYPE})
public @interface SqlInterceptorAnno {
String value() default "";
}
⑤:自定义拦截器配置类
@Configuration
public class SqlInterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SqlInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/login", "/register");
}
}
最后最后!!!
一定要在启动类添加扫描
@ServletComponentScan(basePackages ="全限定名")
以上仅供参考