リッチテキスト連携におけるHTML処理の課題
ウェブアプリケーション開発において、ユーザー入力コンテンツの保存と再表示は頻繁に発生する処理です。生のHTML文字列をそのままリッチテキストエディタに読み込ませる場合、意図しないスクリプトの実行やスタイルの競合、タグの欠損といった問題が生じる可能性があります。Java環境では、HTMLの構文解析、不要な要素の除去、およびエディタ互換フォーマットへの整形をパイプライン化して対応するのが一般的です。
JsoupによるDOM解析とサニタイズ
JsoupはJavaでHTMLをパース・操作するための標準的なライブラリであり、DOMツリーの構築とホワイトリストベースのクリーンアップ機能を提供します。以下の実装では、許可リスト(Safelist)を定義し、入力HTMLから潜在的なリスクを持つ要素を除去しつつ、エディタで編集可能な構造への変換を行います。
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.safety.Safelist;
public class HtmlSanitizer {
private static final Safelist ALLOWED_TAGS = Safelist.relaxed()
.addTags("div", "p", "ul", "ol", "li", "img", "table")
.preserveRelativeLinks(true);
public static String processForEditor(String rawHtml) {
if (rawHtml == null || rawHtml.trim().isEmpty()) {
return "";
}
Document parsed = Jsoup.parseBodyFragment(rawHtml);
String cleaned = Jsoup.clean(parsed.body().html(), ALLOWED_TAGS);
return cleaned.trim();
}
}
テンプレートエンジンを用いた出力整形
サニタイズ済みのHTMLフラグメントは、そのままではエディタの初期化コンテキストに適合しない場合があります。Thymeleafなどのテンプレートエンジンを利用することで、変数の埋め込みやラッパー構造の動的生成を安全に実行できます。以下のコードでは、テンプレートエンジンに対してHTMLコンテキストをセットし、エディタ用の入力フィールド構造をレンダリングします。
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.StringTemplateResolver;
public class EditorContentRenderer {
private final TemplateEngine engine;
public EditorContentRenderer() {
this.engine = new TemplateEngine();
StringTemplateResolver resolver = new StringTemplateResolver();
resolver.setTemplateMode("HTML");
resolver.setCacheable(false);
this.engine.setTemplateResolver(resolver);
}
public String generateEditorPayload(String processedHtml) {
Context ctx = new Context();
ctx.setVariable("contentBody", processedHtml);
String template = "<div id=\"editor-wrapper\"><textarea name=\"raw_content\">[[${contentBody}]]</textarea></div>";
return engine.process(template, ctx);
}
}
処理パイプラインの統合
解析・サニタイズモジュールとレンダリングモジュールを組み合わせることで、外部入力からエディタ表示用の安全なデータセットを生成する一連の流れが完成します。実行時には、不正なタグの除去とコンテキスト変数へのマッピングが自動的に行われます。
public class MainPipeline {
public static void main(String[] args) {
String source = "<p>Sample <b>text</b> with <script>alert('xss')</script></p>";
String sanitized = HtmlSanitizer.processForEditor(source);
EditorContentRenderer renderer = new EditorContentRenderer();
String finalOutput = renderer.generateEditorPayload(sanitized);
System.out.println(finalOutput);
}
}
この構成により、クライアントサイドの表示安定性とサーバーサイドのセキュリティ要件を両立したHTML変換処理が実現されます。