本文目录导读:

我来为您详细解释 JEditorPane、HTMLEditorKit 和 ParserMethodFilter 在 Java Swing 中的使用。
这三个组件通常一起使用来实现 HTML 内容的解析和过滤功能:
- JEditorPane:Swing 中的 HTML 显示组件
- HTMLEditorKit:负责 HTML 的编辑和显示
- ParserMethodFilter:用于过滤 HTML 解析过程中的特定元素
基本使用示例
import javax.swing.*;
import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;
public class HTMLFilterExample {
public static void main(String[] args) {
JFrame frame = new JFrame("HTML Filter Example");
JEditorPane editorPane = new JEditorPane();
// 创建并配置 HTMLEditorKit
HTMLEditorKit kit = new HTMLEditorKit();
// 设置自定义的 ParserMethodFilter
HTMLParser parser = new HTMLParser() {
@Override
protected HTMLParserCallback createParserCallback() {
return new HTMLParserCallback() {
@Override
public void handleStartTag(TagElement tag, MutableAttributeSet attrs) {
if (!shouldFilter(tag)) {
super.handleStartTag(tag, attrs);
}
}
@Override
public void handleEndTag(TagElement tag) {
if (!shouldFilter(tag)) {
super.handleEndTag(tag);
}
}
private boolean shouldFilter(TagElement tag) {
String tagName = tag.getHTMLTag().toString();
// 过滤特定的标签
return tagName.equals("script") ||
tagName.equals("iframe");
}
};
}
};
// 应用设置
kit.setParser(parser);
editorPane.setEditorKit(kit);
// 加载 HTML 内容
String html = "<html><body>" +
"<h1>Hello World</h1>" +
"<script>alert('XSS');</script>" +
"<p>Safe content</p>" +
"</body></html>";
editorPane.setText(html);
editorPane.setEditable(false);
frame.add(new JScrollPane(editorPane));
frame.setSize(500, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
自定义 ParserMethodFilter
public class CustomParserMethodFilter {
// 使用 ParserMethodFilter 过滤特定 HTML 元素
public static void applyFilter(JEditorPane editorPane) {
HTMLEditorKit kit = (HTMLEditorKit) editorPane.getEditorKit();
// 创建过滤器
ParserMethodFilter filter = new ParserMethodFilter() {
@Override
public boolean acceptMethod(String methodName) {
// 只允许特定的解析方法
return methodName.equals("handleStartTag") ||
methodName.equals("handleEndTag") ||
methodName.equals("handleSimpleTag") ||
methodName.equals("handleText");
}
@Override
public boolean acceptParameter(String methodName,
Object[] parameters) {
// 对特定参数进行过滤
if (methodName.equals("handleStartTag")) {
if (parameters.length > 0 &&
parameters[0] instanceof HTML.Tag) {
HTML.Tag tag = (HTML.Tag) parameters[0];
// 阻止 script 标签的解析
return !tag.equals(HTML.Tag.SCRIPT);
}
}
return true;
}
};
// 应用过滤器
// 注意:这里需要扩展 HTMLEditorKit 或使用反射机制
}
}
完整的高级示例
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;
import java.awt.*;
import java.io.*;
import java.net.*;
public class AdvancedHTMLFilterDemo extends JFrame {
private JEditorPane editorPane;
private JTextArea logArea;
public AdvancedHTMLFilterDemo() {
setTitle("HTML Filter Demo");
setLayout(new BorderLayout());
// 创建编辑器面板
editorPane = new JEditorPane();
editorPane.setContentType("text/html");
// 自定义 HTMLEditorKit
CustomHTMLKit kit = new CustomHTMLKit();
editorPane.setEditorKit(kit);
editorPane.setEditable(false);
// 日志面板
logArea = new JTextArea(5, 40);
logArea.setEditable(false);
// 控制按钮
JButton loadButton = new JButton("Load HTML");
loadButton.addActionListener(e -> loadSampleHTML());
// 布局
add(new JScrollPane(editorPane), BorderLayout.CENTER);
add(new JScrollPane(logArea), BorderLayout.SOUTH);
add(loadButton, BorderLayout.NORTH);
setSize(600, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void loadSampleHTML() {
String html = "<html>\n" +
"<head><title>Test</title></head>\n" +
"<body>\n" +
" <h1>Safe Content</h1>\n" +
" <p>This is safe paragraph</p>\n" +
" <script>alert('Blocked!');</script>\n" +
" <a href='https://example.com'>Link</a>\n" +
" <iframe src='https://evil.com'></iframe>\n" +
"</body>\n" +
"</html>";
editorPane.setText(html);
}
// 自定义 HTMLEditorKit
class CustomHTMLKit extends HTMLEditorKit {
@Override
public Document createDefaultDocument() {
HTMLDocument doc = new HTMLDocument() {
@Override
public HTMLEditorKit.ParserCallback getReader(int pos) {
return new FilteredHTMLReader(pos);
}
};
return doc;
}
private class FilteredHTMLReader extends HTMLDocument.HTMLReader {
public FilteredHTMLReader(int offset) {
super(offset);
}
@Override
public void handleStartTag(TagElement t,
MutableAttributeSet a,
int pos) {
String tagName = t.getHTMLTag().toString();
// 过滤不安全标签
if (tagName.equals("script") || tagName.equals("iframe")) {
logArea.append("Filtered out: <" + tagName + ">\n");
return; // 跳过该标签
}
// 过滤特定属性
if (tagName.equals("a") || tagName.equals("img")) {
String src = (String) a.getAttribute(HTML.Attribute.SRC);
String href = (String) a.getAttribute(HTML.Attribute.HREF);
if (src != null && src.startsWith("javascript:")) {
logArea.append("Blocked javascript in src\n");
return;
}
if (href != null && href.startsWith("javascript:")) {
logArea.append("Blocked javascript in href\n");
return;
}
}
super.handleStartTag(t, a, pos);
}
@Override
public void handleSimpleTag(TagElement t,
MutableAttributeSet a,
int pos) {
String tagName = t.getHTMLTag().toString();
if (tagName.equals("img")) {
String src = (String) a.getAttribute(HTML.Attribute.SRC);
if (src != null && !isValidImageSource(src)) {
logArea.append("Blocked image: " + src + "\n");
return;
}
}
super.handleSimpleTag(t, a, pos);
}
private boolean isValidImageSource(String src) {
return !src.startsWith("data:") ||
src.startsWith("data:image/");
}
}
}
// 更高级的过滤器 - 使用 ParserMethodFilter
class SecurityFilter implements ParserMethodFilter {
@Override
public boolean acceptMethod(String methodName) {
// 允许的解析方法
String[] allowedMethods = {
"handleStartTag", "handleEndTag", "handleSimpleTag",
"handleText", "handleComment", "handleError"
};
for (String method : allowedMethods) {
if (method.equals(methodName)) {
return true;
}
}
return false;
}
@Override
public boolean acceptParameter(String methodName,
Object[] parameters) {
// 对特定方法进行参数验证
if (methodName.equals("handleStartTag")) {
if (parameters.length >= 1 &&
parameters[0] instanceof TagElement) {
TagElement tag = (TagElement) parameters[0];
String tagName = tag.getHTMLTag().toString();
// 黑名单标签
String[] blacklist = {
"script", "iframe", "object", "embed", "applet"
};
for (String blocked : blacklist) {
if (tagName.equals(blocked)) {
logArea.append("Blocked tag: " + tagName + "\n");
return false;
}
}
}
}
// 检查属性中的潜在危险内容
if (methodName.equals("handleStartTag") ||
methodName.equals("handleSimpleTag")) {
if (parameters.length >= 2 &&
parameters[1] instanceof MutableAttributeSet) {
MutableAttributeSet attrs =
(MutableAttributeSet) parameters[1];
// 检查事件处理器
Enumeration<?> attrNames = attrs.getAttributeNames();
while (attrNames.hasMoreElements()) {
Object attrName = attrNames.nextElement();
if (attrName instanceof HTML.Attribute) {
HTML.Attribute attr = (HTML.Attribute) attrName;
if (attr.toString().startsWith("on")) {
logArea.append("Blocked event handler: " +
attr + "\n");
return false;
}
}
}
}
}
return true;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new AdvancedHTMLFilterDemo().setVisible(true);
});
}
}
使用 ParserMethodFilter 的安全过滤
import javax.swing.text.html.parser.*;
public class SecureHTMLParser extends DocumentParser {
private ParserMethodFilter filter;
public SecureHTMLParser() {
this.filter = new DefaultFilter();
}
public SecureHTMLParser(ParserMethodFilter filter) {
this.filter = filter;
}
@Override
protected void handleStartTag(TagElement tag) {
if (filter.acceptMethod("handleStartTag")) {
Object[] params = {tag, getAttributes()};
if (filter.acceptParameter("handleStartTag", params)) {
super.handleStartTag(tag);
} else {
logWarning("Start tag filtered: " + tag.getHTMLTag());
}
}
}
@Override
protected void handleEndTag(TagElement tag) {
if (filter.acceptMethod("handleEndTag")) {
super.handleEndTag(tag);
}
}
private void logWarning(String message) {
System.err.println("[Security] " + message);
}
// 默认过滤器实现
static class DefaultFilter implements ParserMethodFilter {
@Override
public boolean acceptMethod(String methodName) {
return true; // 默认接受所有方法
}
@Override
public boolean acceptParameter(String methodName,
Object[] parameters) {
return true; // 默认接受所有参数
}
}
}
使用建议
- 性能考虑:过滤操作会增加解析时间,建议在需要时启用
- 安全级别:根据应用需求选择合适的过滤策略
- 兼容性:确保过滤后的 HTML 仍然保持正确的结构和显示
- 错误处理:做好过滤异常的处理和日志记录
这个示例展示了如何使用 JEditorPane、HTMLEditorKit 和 ParserMethodFilter 来实现 HTML 内容的安全过滤和自定义解析。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播