RuoYi XSS防护:跨站脚本攻击防御
什么是XSS攻击?
XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的Web安全漏洞,攻击者通过在Web页面中注入恶意脚本,当其他用户浏览该页面时,恶意脚本会在用户的浏览器中执行,从而窃取用户信息、会话令牌或进行其他恶意操作。
XSS攻击的三种类型
| 攻击类型 | 特点 | 危害程度 |
|---|---|---|
| 反射型XSS | 恶意脚本通过URL参数注入,服务器返回时包含恶意代码 | ⭐⭐⭐ |
| 存储型XSS | 恶意脚本存储在服务器端,每次访问页面都会执行 | ⭐⭐⭐⭐⭐ |
| DOM型XSS | 完全在客户端执行,不经过服务器处理 | ⭐⭐⭐⭐ |
RuoYi XSS防护架构
RuoYi采用多层次、深度防御的XSS防护策略,确保系统安全可靠。
核心防护组件
1. XSS过滤器(XssFilter)
XSS过滤器是防护体系的第一道防线,基于Servlet Filter机制实现:
public class XssFilter implements Filter {
private List<String> excludes = new ArrayList<>();
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
HttpServletRequest req = (HttpServletRequest) request;
if (handleExcludeURL(req)) {
chain.doFilter(request, response);
return;
}
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(req);
chain.doFilter(xssRequest, response);
}
private boolean handleExcludeURL(HttpServletRequest request) {
String url = request.getServletPath();
String method = request.getMethod();
// GET和DELETE请求不过滤
if (method == null || method.matches("GET") || method.matches("DELETE")) {
return true;
}
return StringUtils.matches(url, excludes);
}
}
2. XSS请求包装器(XssHttpServletRequestWrapper)
对请求参数进行实时过滤处理:
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values != null) {
String[] escapseValues = new String[values.length];
for (int i = 0; i < values.length; i++) {
// 防xss攻击和过滤前后空格
escapseValues[i] = EscapeUtil.clean(values[i]).trim();
}
return escapseValues;
}
return super.getParameterValues(name);
}
}
3. HTML过滤器(HTMLFilter)
专业的HTML标签和属性过滤引擎:
public class HTMLFilter {
// 允许的HTML标签和属性白名单
private final Map<String, List<String>> vAllowed = new HashMap<>();
public HTMLFilter() {
// 配置允许的标签和属性
final ArrayList<String> a_atts = new ArrayList<>();
a_atts.add("href");
a_atts.add("target");
vAllowed.put("a", a_atts);
final ArrayList<String> img_atts = new ArrayList<>();
img_atts.add("src");
img_atts.add("width");
img_atts.add("height");
img_atts.add("alt");
vAllowed.put("img", img_atts);
// 更多白名单配置...
}
public String filter(final String input) {
reset();
String s = input;
s = escapeComments(s); // 转义注释
s = balanceHTML(s); // 平衡HTML标签
s = checkTags(s); // 检查标签合法性
s = processRemoveBlanks(s); // 处理空白标签
return s;
}
}
4. 转义工具(EscapeUtil)
提供字符转义和反转义功能:
public class EscapeUtil {
private static final char[][] TEXT = new char[64][];
static {
// 特殊HTML字符转义映射
TEXT['\''] = "'".toCharArray(); // 单引号
TEXT['"'] = """.toCharArray(); // 双引号
TEXT['&'] = "&".toCharArray(); // &符
TEXT['<'] = "<".toCharArray(); // 小于号
TEXT['>'] = ">".toCharArray(); // 大于号
}
public static String clean(String content) {
return new HTMLFilter().filter(content);
}
}
配置详解
配置文件设置
在application.yml中配置XSS防护参数:
# 防止XSS攻击配置
xss:
# 过滤开关
enabled: true
# 排除链接(多个用逗号分隔)
excludes: /system/notice/*
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*
过滤规则说明
| 配置项 | 说明 | 示例值 |
|---|---|---|
| enabled | 是否启用XSS过滤 | true/false |
| excludes | 排除的URL模式 | /system/notice/* |
| urlPatterns | 需要过滤的URL模式 | /system/*,/monitor/* |
过滤器注册配置
@Configuration
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
public class FilterConfig {
@Bean
public FilterRegistrationBean xssFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new XssFilter());
registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
registration.setName("xssFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
Map<String, String> initParameters = new HashMap<>();
initParameters.put("excludes", excludes);
registration.setInitParameters(initParameters);
return registration;
}
}
防护效果演示
攻击示例与防护结果
// 攻击示例1:脚本注入
String maliciousInput = "<script>alert('XSS攻击')</script>";
String cleaned = EscapeUtil.clean(maliciousInput);
// 输出:alert('XSS攻击')
// 攻击示例2:事件处理器注入
String eventInput = "<img src=x onerror=alert('XSS')>";
String cleaned2 = EscapeUtil.clean(eventInput);
// 输出:<img src="x">
// 攻击示例3:JavaScript协议注入
String jsInput = "<a href=\"javascript:alert('XSS')\">点击</a>";
String cleaned3 = EscapeUtil.clean(jsInput);
// 输出:<a href="#">点击</a>
防护机制对比表
| 防护层面 | 技术实现 | 防护效果 | 性能影响 |
|---|---|---|---|
| 输入过滤 | XSS过滤器拦截 | 拦截恶意请求 | 低 |
| 参数处理 | 请求包装器处理 | 实时参数过滤 | 中 |
| 内容清洗 | HTML过滤器清洗 | 深度内容净化 | 中 |
| 输出编码 | 字符转义处理 | 防止脚本执行 | 低 |
最佳实践指南
1. 配置建议
# 推荐配置
xss:
enabled: true
excludes: /api/public/*,/druid/*
urlPatterns: /**
2. 自定义过滤规则
如果需要扩展过滤规则,可以继承HTMLFilter类:
public class CustomHTMLFilter extends HTMLFilter {
public CustomHTMLFilter() {
super();
// 添加自定义允许的标签和属性
ArrayList<String> customAtts = new ArrayList<>();
customAtts.add("data-custom");
vAllowed.put("div", customAtts);
}
@Override
public String filter(String input) {
// 自定义过滤逻辑
String filtered = super.filter(input);
// 额外的处理
return filtered;
}
}
3. 性能优化建议
// 使用缓存提高性能
private static final Map<String, String> FILTER_CACHE = new ConcurrentHashMap<>();
public static String safeFilter(String content) {
if (FILTER_CACHE.containsKey(content)) {
return FILTER_CACHE.get(content);
}
String filtered = new HTMLFilter().filter(content);
FILTER_CACHE.put(content, filtered);
return filtered;
}
常见问题解答
Q1: 为什么需要排除某些URL?
某些场景下(如富文本编辑器、公告发布等)需要允许HTML内容,通过excludes配置可以灵活控制。
Q2: 如何测试XSS防护效果?
可以使用以下测试向量:
<script>alert('XSS')</script><img src=x onerror=alert(1)><a href="javascript:alert('XSS')">test</a>
Q3: 防护机制会影响正常业务吗?
RuoYi的防护机制经过精心设计,只在必要时进行过滤,不会影响正常业务功能。
总结
RuoYi的XSS防护体系提供了全面、高效的安全保障:
- 多层次防御:从请求拦截到内容过滤的多层防护
- 灵活配置:支持URL模式匹配和排除规则
- 高性能:优化的过滤算法确保系统性能
- 易扩展:支持自定义过滤规则和扩展
通过合理配置和使用RuoYi的XSS防护功能,可以有效防止跨站脚本攻击,保障Web应用的安全稳定运行。
提示:建议定期更新系统,关注安全公告,及时修复可能的安全漏洞。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



