RuoYi
2020-03-13 ab992f4848d663b0ca5dc65883b05ad950eae778
修复防重复提交注解无效问题
已重命名2个文件
已修改2个文件
已添加2个文件
185 ■■■■■ 文件已修改
ruoyi/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi/src/main/java/com/ruoyi/common/filter/XssFilter.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi/src/main/java/com/ruoyi/framework/config/FilterConfig.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java 31 ●●●● 补丁 | 查看 | 原始文档 | 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;
    }