在 Java 中处理 HTML 特殊字符的转义,是为了确保内容在浏览器中正确显示并防止 XSS(跨站脚本攻击)。
HTML常见特殊字符
字符 | 实体名称 | 实体编号 |
& | & | & |
< | < | < |
> | > | > |
" | " | " |
' | ' 或 ' | ' |
空格 |
|
|
(c) | © | © |
(R) | ® | ® |
EUR | € | € |
≥ | ≥ | ≥ |
一、为什么需要转义?
当动态内容(如用户输入、数据库数据)包含以下字符时,直接输出到 HTML 会导致解析错误导致内容展示异常或安全问题:
- & → 需转义为 &
- < → 需转义为 <
- > → 需转义为 >
- " → 需转义为 "
- ' → 需转义为 ' 或 '
二、Java 中转义 HTML 的方法
1. 手动替换(简单场景)
适用于少量字符或简单项目:
public class HtmlEscapeManual {
public static String escape(String input) {
if (input == null) return "";
return input.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace("\"", """)
.replace("'", "'");
}
public static void main(String[] args) {
String text = "<script>alert('XSS')</script>";
System.out.println(escape(text));
// 输出:<script>alert('XSS')</script>
}
}
缺点:容易遗漏字符,且不支持 Unicode 字符。
2. 使用 Apache Commons Text 库
推荐方法,功能全面且高效:
- 添加 Maven 依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.10.0</version>
</dependency>
- 代码示例:
import org.apache.commons.text.StringEscapeUtils;
public class HtmlEscapeCommons {
public static void main(String[] args) {
String text = "John & Doe's <script>alert('XSS')</script>";
String escaped = StringEscapeUtils.escapeHtml4(text);
System.out.println(escaped);
// 输出:John & Doe's <script>alert('XSS')</script>
}
}
优势:
- 自动处理所有标准 HTML 实体。
- 支持 escapeHtml4()(HTML4)和 escapeHtml5()(HTML5)。
3. 使用 Spring Framework 的 HtmlUtils
适用于 Spring 项目:
- 添加依赖(若未引入 Spring):
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.23</version>
</dependency>
- 代码示例:
import org.springframework.web.util.HtmlUtils;
public class HtmlEscapeSpring {
public static void main(String[] args) {
String text = "Price: < 100 EUR";
String escaped = HtmlUtils.htmlEscape(text);
System.out.println(escaped);
// 输出:Price: < 100 EUR
}
}
特点:
- 直接转义为实体(如 EUR → €)。
- 支持双向转义(htmlEscape 和 htmlUnescape)。
4. 处理动态内容(如用户输入)
从数据库或请求参数中获取数据时,必须转义:
// 示例:从 HTTP 请求中获取参数并转义
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.text.StringEscapeUtils;
public class UserController {
public void handleRequest(HttpServletRequest request) {
String userInput = request.getParameter("comment");
String safeComment = StringEscapeUtils.escapeHtml4(userInput);
// 输出到 HTML 页面
request.setAttribute("comment", safeComment);
}
}
三、注意事项
- 编码一致性:
- 确保 HTML 页面声明 <meta charset="UTF-8">。
- Java 文件保存为 UTF-8 格式,避免乱码。
- 避免双重转义:
- 如果数据已被转义,再次转义会导致显示异常(如 &)。
- XSS 防御:
- 对用户输入的内容不仅要转义,还需过滤敏感内容(如 <script> 标签)。
- 性能优化:
- 频繁转义时,使用缓存或预编译工具(如 Apache Commons Text 的 StringEscapeUtils)。
四、完整示例(Spring Boot 项目)
1. Controller 层转义
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.util.HtmlUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
@Controller
public class DemoController {
@GetMapping("/greeting")
public String greeting(@RequestParam String name, Model model) {
String safeName = HtmlUtils.htmlEscape(name); // 转义用户输入
model.addAttribute("name", safeName);
return "greeting";
}
}
2. Thymeleaf 模板渲染
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
</head>
<body>
<p>Hello, <span th:text="${name}">User</span>!</p>
</body>
</html>
输入:<script>alert('XSS')</script>
输出:Hello, <script>alert('XSS')</script>!
五、总结
方法 | 适用场景 | 优点 | 缺点 |
手动替换 | 简单、临时需求 | 无需依赖库 | 易出错、不全面 |
Apache Commons Text | 通用场景 | 功能全面、高效 | 需添加依赖 |
Spring HtmlUtils | Spring 项目 | 集成方便 | 仅限 Spring 环境 |
推荐方案:优先使用 Apache Commons Text,兼顾功能和安全;在 Spring 项目中可直接使用 HtmlUtils。