ruoyi/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
ruoyi/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
ruoyi/src/main/java/com/ruoyi/common/filter/XssFilter.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
ruoyi/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
ruoyi/src/main/java/com/ruoyi/framework/config/FilterConfig.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
ruoyi/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
ruoyi/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java
对比新文件 @@ -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() { } } ruoyi/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java
对比新文件 @@ -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; } } ruoyi/src/main/java/com/ruoyi/common/filter/XssFilter.java
文件名从 ruoyi/src/main/java/com/ruoyi/common/xss/XssFilter.java 修改 @@ -1,4 +1,4 @@ package com.ruoyi.common.xss; package com.ruoyi.common.filter; import java.io.IOException; import java.util.ArrayList; ruoyi/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
文件名从 ruoyi/src/main/java/com/ruoyi/common/xss/XssHttpServletRequestWrapper.java 修改 @@ -1,4 +1,4 @@ package com.ruoyi.common.xss; package com.ruoyi.common.filter; import java.io.ByteArrayInputStream; import java.io.IOException; ruoyi/src/main/java/com/ruoyi/framework/config/FilterConfig.java
@@ -7,8 +7,9 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; 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.xss.XssFilter; /** * Filter配置 @@ -36,11 +37,24 @@ registration.setFilter(new XssFilter()); registration.addUrlPatterns(StringUtils.split(urlPatterns, ",")); registration.setName("xssFilter"); registration.setOrder(Integer.MAX_VALUE); registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE); Map<String, String> initParameters = new HashMap<String, String>(); initParameters.put("excludes", excludes); initParameters.put("enabled", enabled); registration.setInitParameters(initParameters); 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; } } ruoyi/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
@@ -2,14 +2,19 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; 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.redis.RedisCache; /** * 判断请求url和数据是否和上一次相同, * 判断请求url和数据是否和上一次相同, * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。 * * @author ruoyi @@ -22,6 +27,9 @@ public final String REPEAT_TIME = "repeatTime"; public final String SESSION_REPEAT_KEY = "repeatData"; @Autowired private RedisCache redisCache; /** * 间隔时间,单位:秒 默认10秒 @@ -39,8 +47,14 @@ @Override public boolean isRepeatSubmit(HttpServletRequest request) { // 本次参数及系统时间 String nowParams = JSONObject.toJSONString(request.getParameterMap()); RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request; String nowParams = HttpHelper.getBodyString(repeatedlyRequest); // body参数为空,获取Parameter的数据 if (StringUtils.isEmpty(nowParams)) { nowParams = JSONObject.toJSONString(request.getParameterMap()); } Map<String, Object> nowDataMap = new HashMap<String, Object>(); nowDataMap.put(REPEAT_PARAMS, nowParams); nowDataMap.put(REPEAT_TIME, System.currentTimeMillis()); @@ -48,8 +62,7 @@ // 请求地址(作为存放session的key值) String url = request.getRequestURI(); HttpSession session = request.getSession(); Object sessionObj = session.getAttribute(SESSION_REPEAT_KEY); Object sessionObj = redisCache.getCacheObject(SESSION_REPEAT_KEY); if (sessionObj != null) { Map<String, Object> sessionMap = (Map<String, Object>) sessionObj; @@ -62,9 +75,9 @@ } } } Map<String, Object> sessionMap = new HashMap<String, Object>(); sessionMap.put(url, nowDataMap); session.setAttribute(SESSION_REPEAT_KEY, sessionMap); Map<String, Object> cacheMap = new HashMap<String, Object>(); cacheMap.put(url, nowDataMap); redisCache.setCacheObject(SESSION_REPEAT_KEY, cacheMap, intervalTime, TimeUnit.SECONDS); return false; }