Skip to content

Commit

Permalink
fix 修复 经过加密的请求无法过滤xss问题 将xss实现从gateway移动到common-web解密后过滤
Browse files Browse the repository at this point in the history
  • Loading branch information
JavaLionLi committed Oct 20, 2024
1 parent f64b17b commit 503a0ef
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 113 deletions.
8 changes: 8 additions & 0 deletions config/nacos/application-common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,14 @@ api-decrypt:
# 对应前端加密公钥 MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==
privateKey: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKNPuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gAkM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWowcSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99EcvDQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthhYhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3UP8iWi1Qw0Y=

# 防止XSS攻击
xss:
enabled: true
excludeUrls:
- /system/notice
- /workflow/model/save
- /workflow/model/editModelXml

# 接口文档配置
springdoc:
api-docs:
Expand Down
7 changes: 0 additions & 7 deletions config/nacos/ruoyi-gateway.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
# 安全配置
security:
# 防止XSS攻击
xss:
enabled: true
excludeUrls:
- /system/notice
- /workflow/model/save
- /workflow/model/editModelXml
# 不校验白名单
ignore:
whites:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.dromara.common.web.config;

import jakarta.servlet.DispatcherType;
import org.dromara.common.web.config.properties.XssProperties;
import org.dromara.common.web.filter.XssFilter;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;

/**
* Filter配置
*
* @author Lion Li
*/
@AutoConfiguration
@EnableConfigurationProperties(XssProperties.class)
public class FilterConfig {

@Bean
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
public FilterRegistrationBean<XssFilter> xssFilterRegistration() {
FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter());
registration.addUrlPatterns("/*");
registration.setName("xssFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE + 1);
return registration;
}

}
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
package org.dromara.gateway.config.properties;
package org.dromara.common.web.config.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

/**
* XSS跨站脚本配置
*
* @author ruoyi
* @author Lion Li
*/
@Data
@Configuration
@RefreshScope
@ConfigurationProperties(prefix = "security.xss")
@ConfigurationProperties(prefix = "xss")
public class XssProperties {

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.dromara.common.web.filter;

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.web.config.properties.XssProperties;
import org.springframework.http.HttpMethod;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
* 防止XSS攻击的过滤器
*
* @author ruoyi
*/
public class XssFilter implements Filter {
/**
* 排除链接
*/
public List<String> excludes = new ArrayList<>();

@Override
public void init(FilterConfig filterConfig) throws ServletException {
XssProperties properties = SpringUtils.getBean(XssProperties.class);
String appName = SpringUtils.getApplicationName();
String appPath = "/" + StringUtils.substring(appName, appName.indexOf("-") + 1);
List<String> excludeUrls = properties.getExcludeUrls()
.stream()
.filter(x -> StringUtils.startsWith(x, appPath))
.map(x -> x.replaceFirst(appPath, StringUtils.EMPTY))
.toList();
excludes.addAll(excludeUrls);
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if (handleExcludeURL(req, resp)) {
chain.doFilter(request, response);
return;
}
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}

private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) {
String url = request.getServletPath();
String method = request.getMethod();
// GET DELETE 不过滤
if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method)) {
return true;
}
return StringUtils.matches(url, excludes);
}

@Override
public void destroy() {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package org.dromara.common.web.filter;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.dromara.common.core.utils.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
* XSS过滤处理
*
* @author ruoyi
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
/**
* @param request
*/
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}

@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values != null) {
int length = values.length;
String[] escapseValues = new String[length];
for (int i = 0; i < length; i++) {
// 防xss攻击和过滤前后空格
escapseValues[i] = HtmlUtil.cleanHtmlTag(values[i]).trim();
}
return escapseValues;
}
return super.getParameterValues(name);
}

@Override
public ServletInputStream getInputStream() throws IOException {
// 非json类型,直接返回
if (!isJsonRequest()) {
return super.getInputStream();
}

// 为空,直接返回
String json = StrUtil.str(IoUtil.readBytes(super.getInputStream(), false), StandardCharsets.UTF_8);
if (StringUtils.isEmpty(json)) {
return super.getInputStream();
}

// xss过滤
json = HtmlUtil.cleanHtmlTag(json).trim();
byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8);
final ByteArrayInputStream bis = IoUtil.toStream(jsonBytes);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return true;
}

@Override
public boolean isReady() {
return true;
}

@Override
public int available() throws IOException {
return jsonBytes.length;
}

@Override
public void setReadListener(ReadListener readListener) {
}

@Override
public int read() throws IOException {
return bis.read();
}
};
}

/**
* 是否是Json请求
*/
public boolean isJsonRequest() {
String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
org.dromara.common.web.config.FilterConfig
org.dromara.common.web.config.I18nConfig
org.dromara.common.web.config.UndertowConfig
org.dromara.common.web.config.ResourcesConfig
org.dromara.common.web.config.ResourcesConfig
100 changes: 0 additions & 100 deletions ruoyi-gateway/src/main/java/org/dromara/gateway/filter/XssFilter.java

This file was deleted.

0 comments on commit 503a0ef

Please sign in to comment.