修复防重复提交注解无效问题

This commit is contained in:
RuoYi 2020-03-13 21:15:50 +08:00
parent baea48be68
commit ab992f4848
6 changed files with 172 additions and 13 deletions

View File

@ -0,0 +1,48 @@
package com.ruoyi.common.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import com.ruoyi.common.enums.HttpMethod;
/**
* Repeatable 过滤器
*
* @author ruoyi
*/
public class RepeatableFilter implements Filter
{
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest req = (HttpServletRequest) request;
if (HttpMethod.PUT.name().equals(req.getMethod()) || HttpMethod.POST.name().equals(req.getMethod()))
{
RepeatedlyRequestWrapper repeatedlyRequest = new RepeatedlyRequestWrapper((HttpServletRequest) request);
chain.doFilter(repeatedlyRequest, response);
}
else
{
chain.doFilter(request, response);
}
}
@Override
public void destroy()
{
}
}

View File

@ -0,0 +1,84 @@
package com.ruoyi.common.filter;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import com.ruoyi.common.utils.StringUtils;
/**
* 构建可重复读取inputStream的request
*
* @author ruoyi
*/
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
{
private final byte[] body;
public RepeatedlyRequestWrapper(HttpServletRequest request) throws IOException
{
super(request);
body = readBytes(request.getReader(), "utf-8");
}
@Override
public BufferedReader getReader() throws IOException
{
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException
{
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream()
{
@Override
public boolean isFinished()
{
return false;
}
@Override
public boolean isReady()
{
return false;
}
@Override
public void setReadListener(ReadListener listener)
{
}
@Override
public int read() throws IOException
{
return bais.read();
}
};
}
/**
* 通过BufferedReader和字符编码集转换成byte数组
*/
private byte[] readBytes(BufferedReader br, String encoding) throws IOException
{
String str = null, retStr = "";
while ((str = br.readLine()) != null)
{
retStr += str;
}
if (StringUtils.isNotBlank(retStr))
{
return retStr.getBytes(Charset.forName(encoding));
}
return null;
}
}

View File

@ -1,4 +1,4 @@
package com.ruoyi.common.xss; package com.ruoyi.common.filter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;

View File

@ -1,4 +1,4 @@
package com.ruoyi.common.xss; package com.ruoyi.common.filter;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;

View File

@ -7,8 +7,9 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import com.ruoyi.common.filter.RepeatableFilter;
import com.ruoyi.common.filter.XssFilter;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.xss.XssFilter;
/** /**
* Filter配置 * Filter配置
@ -36,11 +37,24 @@ public class FilterConfig
registration.setFilter(new XssFilter()); registration.setFilter(new XssFilter());
registration.addUrlPatterns(StringUtils.split(urlPatterns, ",")); registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
registration.setName("xssFilter"); registration.setName("xssFilter");
registration.setOrder(Integer.MAX_VALUE); registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
Map<String, String> initParameters = new HashMap<String, String>(); Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("excludes", excludes); initParameters.put("excludes", excludes);
initParameters.put("enabled", enabled); initParameters.put("enabled", enabled);
registration.setInitParameters(initParameters); registration.setInitParameters(initParameters);
return registration; return registration;
} }
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean someFilterRegistration()
{
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new RepeatableFilter());
registration.addUrlPatterns("/*");
registration.setName("repeatableFilter");
registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
return registration;
}
} }

View File

@ -2,14 +2,19 @@ package com.ruoyi.framework.interceptor.impl;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.filter.RepeatedlyRequestWrapper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpHelper;
import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
import com.ruoyi.framework.redis.RedisCache;
/** /**
* 判断请求url和数据是否和上一次相同 * 判断请求url和数据是否和上一次相同
* 如果和上次相同则是重复提交表单 有效时间为10秒内 * 如果和上次相同则是重复提交表单 有效时间为10秒内
* *
* @author ruoyi * @author ruoyi
@ -23,6 +28,9 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
public final String SESSION_REPEAT_KEY = "repeatData"; public final String SESSION_REPEAT_KEY = "repeatData";
@Autowired
private RedisCache redisCache;
/** /**
* 间隔时间单位: 默认10秒 * 间隔时间单位: 默认10秒
* *
@ -39,8 +47,14 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
@Override @Override
public boolean isRepeatSubmit(HttpServletRequest request) public boolean isRepeatSubmit(HttpServletRequest request)
{ {
// 本次参数及系统时间 RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
String nowParams = JSONObject.toJSONString(request.getParameterMap()); String nowParams = HttpHelper.getBodyString(repeatedlyRequest);
// body参数为空获取Parameter的数据
if (StringUtils.isEmpty(nowParams))
{
nowParams = JSONObject.toJSONString(request.getParameterMap());
}
Map<String, Object> nowDataMap = new HashMap<String, Object>(); Map<String, Object> nowDataMap = new HashMap<String, Object>();
nowDataMap.put(REPEAT_PARAMS, nowParams); nowDataMap.put(REPEAT_PARAMS, nowParams);
nowDataMap.put(REPEAT_TIME, System.currentTimeMillis()); nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
@ -48,8 +62,7 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
// 请求地址作为存放session的key值 // 请求地址作为存放session的key值
String url = request.getRequestURI(); String url = request.getRequestURI();
HttpSession session = request.getSession(); Object sessionObj = redisCache.getCacheObject(SESSION_REPEAT_KEY);
Object sessionObj = session.getAttribute(SESSION_REPEAT_KEY);
if (sessionObj != null) if (sessionObj != null)
{ {
Map<String, Object> sessionMap = (Map<String, Object>) sessionObj; Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
@ -62,9 +75,9 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
} }
} }
} }
Map<String, Object> sessionMap = new HashMap<String, Object>(); Map<String, Object> cacheMap = new HashMap<String, Object>();
sessionMap.put(url, nowDataMap); cacheMap.put(url, nowDataMap);
session.setAttribute(SESSION_REPEAT_KEY, sessionMap); redisCache.setCacheObject(SESSION_REPEAT_KEY, cacheMap, intervalTime, TimeUnit.SECONDS);
return false; return false;
} }