0

Vaadin がブラウザーに送信するブートストラップ Javascript を変更しようとしています。この問題に関する Vaadin フォーラムのリンクは次のとおりです: https://vaadin.com/forum#!/thread/4252604

Vaadin は Jsoup を使用するため、Jsoup API を使用して、Vaadin ペイロード内の適切な場所を見つけて Javascript を変更しています。Jsoup API を次のように使用すると、次のようになります。

element.html(newHTML)

newHTML にあったものはすべてエスケープされます。たとえば、newHTML が次の場合:

alert("hi");

Jsoup API を呼び出すと、次のようになります。

alert("hi");

次のようなことを行うことで、この Jsoup エスケープを無効にできると思いました。

element.ownerDocument().outputSettings().escapeMode(...)

しかし、 ownerDocument() は null なので、それはオプションではないと思います。Jsoup にはこの制限を回避する方法があり、出力を取得するために二重引用符 (") を含む Javascript を取得できますか?

4

2 に答える 2

0

どうやら、

element.childNode(0).attr("data", html);

要素が「スクリプト」要素であり、htmlが Javascript ソースである場合、トリックを行います。

于 2013-10-28T19:08:53.563 に答える
0

私の解決策は、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( &quot;Hello World!&quot; );</script>

以前に発生していたように。

私が見つけた2つの「落とし穴」がありました:

  • UnescapedTextNode クラスは、元の jsoup ライブラリをロードするのと同じクラスローダーによってロードされる必要があります。これは、上記で package-private メソッドをオーバーライドしており、JLS で規定されているためです。(これを指摘してくれた記事を書いてくれた Jeff Sinclair に感謝します。適切な点は、

    フィールドまたはメソッド R は、次の条件のいずれかが真である場合にのみ、クラスまたはインターフェイス D からアクセスできます。

    • …</li>
    • R はパッケージ プライベートであり、D と同じランタイム パッケージ内のクラスによって宣言されます。

    これはAccess Control (5.4.4)の下のJVM 仕様にあります。

  • サニタイズされていないデータをドキュメントに挿入するのを防ぐセーフティ ネットを効果的に切り離しているため、これは非常に危険な行為です。アプリケーション ユーザーからこのテキスト ノードに追加するものに html タグ (特に ) が含まれていないことを確認してください。そうしないと、XSS、CSRF などで非常に苦労することになります。
于 2013-11-04T11:19:27.070 に答える