Kaynağa Gözat

!253 修复:非法请求使过滤器失效,出现严重安全问题
* BaseUrlFilter 修改过滤全部路径,保证 BaseUrlFilter 优于UrlCheckFilter 执行
* 清除无用 html
* 非法请求过滤器: 修复请求 path 中包含 // 或者以 / 结尾导致其它过滤器失效,对请求进行重定向
* 非法请求过滤器: 替换 getRequestURI() 为 getServletPath()
* 非法请求过滤器: 截取 context-path
* 非法请求过滤器: 去除 context-path
* 非法请求过滤器: 排除首页path "/"
* 非法请求过滤器: 请求地址中包含"//"或者以"/"结尾时导致其他过滤器失效,比如 TrustHostFilter

Moomel 1 yıl önce
ebeveyn
işleme
448a700687

+ 12 - 4
server/src/main/java/cn/keking/config/WebConfig.java

@@ -30,11 +30,13 @@ public class WebConfig implements WebMvcConfigurer {
         registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/","classpath:/resources/","classpath:/static/","classpath:/public/","file:" + filePath);
     }
 
+
     @Bean
     public FilterRegistrationBean<ChinesePathFilter> getChinesePathFilter() {
         ChinesePathFilter filter = new ChinesePathFilter();
         FilterRegistrationBean<ChinesePathFilter> registrationBean = new FilterRegistrationBean<>();
         registrationBean.setFilter(filter);
+        registrationBean.setOrder(10);
         return registrationBean;
     }
 
@@ -67,14 +69,20 @@ public class WebConfig implements WebMvcConfigurer {
     @Bean
     public FilterRegistrationBean<BaseUrlFilter> getBaseUrlFilter() {
         Set<String> filterUri = new HashSet<>();
-        filterUri.add("/index");
-        filterUri.add("/");
-        filterUri.add("/onlinePreview");
-        filterUri.add("/picturesPreview");
         BaseUrlFilter filter = new BaseUrlFilter();
         FilterRegistrationBean<BaseUrlFilter> registrationBean = new FilterRegistrationBean<>();
         registrationBean.setFilter(filter);
         registrationBean.setUrlPatterns(filterUri);
+        registrationBean.setOrder(20);
+        return registrationBean;
+    }
+
+    @Bean
+    public FilterRegistrationBean<UrlCheckFilter> getUrlCheckFilter() {
+        UrlCheckFilter filter = new UrlCheckFilter();
+        FilterRegistrationBean<UrlCheckFilter> registrationBean = new FilterRegistrationBean<>();
+        registrationBean.setFilter(filter);
+        registrationBean.setOrder(30);
         return registrationBean;
     }
 

+ 52 - 0
server/src/main/java/cn/keking/web/filter/UrlCheckFilter.java

@@ -0,0 +1,52 @@
+package cn.keking.web.filter;
+
+import org.apache.commons.lang3.StringUtils;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * @date 2023/11/30
+ */
+public class UrlCheckFilter implements Filter {
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+
+        final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+        String servletPath = httpServletRequest.getServletPath();
+
+        boolean redirect = false;
+
+        // servletPath 中不能包含 //
+        if (servletPath.contains("//")) {
+            servletPath = servletPath.replaceAll("//+", "/");
+            redirect = true;
+        }
+
+        // 不能以 / 结尾,同时考虑 **首页** 的特殊性
+        if (servletPath.endsWith("/") && servletPath.length() > 1) {
+            servletPath = servletPath.substring(0, servletPath.length() - 1);
+            redirect = true;
+        }
+        if (redirect) {
+            String redirectUrl;
+            if (StringUtils.isBlank(BaseUrlFilter.getBaseUrl())) {
+                // 正常 BaseUrlFilter 有限此 Filter 执行,不会执行到此
+                redirectUrl = httpServletRequest.getContextPath() + servletPath;
+            } else {
+                if (BaseUrlFilter.getBaseUrl().endsWith("/") && servletPath.startsWith("/")) {
+                    // BaseUrlFilter.getBaseUrl() 以 / 结尾,servletPath 以 / 开头,需再去除一次 //
+                    redirectUrl = BaseUrlFilter.getBaseUrl() + servletPath.substring(1);
+                } else {
+                    redirectUrl = BaseUrlFilter.getBaseUrl() + servletPath;
+                }
+            }
+            ((HttpServletResponse) response).sendRedirect(redirectUrl + "?" + httpServletRequest.getQueryString());
+        } else {
+            chain.doFilter(request, response);
+        }
+    }
+}