私の解決策は、TextNode をサブクラス化し、エスケープを行うメソッドをオーバーライドすることでした。
package org.jsoup.nodes;
public class UnescapedTextNode extends TextNode
{
public UnescapedTextNode( final String text, final String baseUri )
{
super( text, baseUri );
}
@Override
void outerHtmlHead(
final StringBuilder accum,
final int depth,
final Document.OutputSettings out )
{
//String html = Entities.escape( getWholeText(), out ); // Don't escape!
String html = getWholeText();
if ( out.prettyPrint() &&
parent() instanceof Element &&
!Element.preserveWhitespace( parent() ) )
{
html = normaliseWhitespace( html );
}
if ( out.prettyPrint() &&
( ( siblingIndex() == 0 &&
parentNode instanceof Element &&
( (Element)parentNode ).tag().formatAsBlock() &&
!isBlank() ) ||
( out.outline() &&
siblingNodes().size() > 0 &&
!isBlank() ) ) )
{
indent( accum, depth, out );
}
accum.append( html );
}
}
TextNode.outerHtmlHead()
これは、 (Jonathan Hedley によって最初に書かれた)のほとんどそのままのコピーです。エスケープ部分をコメントアウトしました。これは私がそれを使用した方法です:
// ... assuming head is of type Element and refers to the <head> of the document.
final String message = "Hello World!";
final String messageScript = "alert( \"" + message + "\" );";
final Element messageScriptEl = head.appendElement( "script" ).
attr( "type", "text/javascript" );
final TextNode messageScriptTextNode = new UnescapedTextNode(
messageScript,
messageScriptEl.baseUri() );
messageScriptEl.appendChild( messageScriptTextNode );
// ... etc
さらに、エスケープされずに作成された script タグ内のテキストを使用して、呼び出しDocument.toString()
または出力を生成します。Document.outerHtml()
すなわち:
<script type="text/javascript">alert( "Hello World!" );</script>
それ以外の:
<script type="text/javascript">alert( "Hello World!" );</script>
以前に発生していたように。
私が見つけた2つの「落とし穴」がありました:
UnescapedTextNode クラスは、元の jsoup ライブラリをロードするのと同じクラスローダーによってロードされる必要があります。これは、上記で package-private メソッドをオーバーライドしており、JLS で規定されているためです。(これを指摘してくれた記事を書いてくれた Jeff Sinclair に感謝します。適切な点は、
フィールドまたはメソッド R は、次の条件のいずれかが真である場合にのみ、クラスまたはインターフェイス D からアクセスできます。
- …</li>
- R はパッケージ プライベートであり、D と同じランタイム パッケージ内のクラスによって宣言されます。
これはAccess Control (5.4.4)の下のJVM 仕様にあります。
- サニタイズされていないデータをドキュメントに挿入するのを防ぐセーフティ ネットを効果的に切り離しているため、これは非常に危険な行為です。アプリケーション ユーザーからこのテキスト ノードに追加するものに html タグ (特に ) が含まれていないことを確認してください。そうしないと、XSS、CSRF などで非常に苦労することになります。