部分をレンダリングする前にescape_javascriptを使用するのはなぜですか?


Answers

コードを2つに分割すると分かりやすくなります。

最初の部分$("#reviews").append("<%= ... %>"); erbのjavascriptです。 つまり、 <%= ... %>はその内部のルビコードが何を返しても置き換えられます。 その置換の結果は有効なjavascriptでなければなりません。それ以外の場合、クライアントがそれを処理しようとするとエラーがスローされます。 それが最初のことです: 有効なjavascriptが必要です

考慮すべきもう一つのことは、ルビが生成するものは二重引用符で囲まれたjavascript文字列の中に含まれなければならないということです - <%= ... %>前後に二重引用符があることに注意してください。 つまり、生成されたjavascriptは次のようになります。

$("#reviews").append("...");

次に、 <%= ... %>中のルビー部分を調べてみましょう。 render(:partial => @review)は何ですか? これは、部分的なレンダリングです。つまり、あらゆる種類のコードをレンダリングすることができます。つまり、html、css、またはさらに多くのjavascriptをレンダリングすることができます。

だから、私たちの部分にこのような単純なHTMLが含まれているとどうなりますか?

<a href="/mycontroller/myaction">Action!</a> 

あなたのJavaScriptは二重引用符で囲まれた文字列をパラメータとして受け取っていたことを覚えていますか? 単に<%= ... %>をその部分のコードに置き換えた場合、問題が発生します。つまり、 href=直後に二重引用符があります。 javascriptは有効ではありません:

// Without escaping, you get a broken javascript string at href
$("#reviews").append("<a href="/mycontroller/myaction">Action!</a>");

これが起こらないようにするには、これらの特殊文字をエスケープして、文字列がカットされないようにします。代わりにこれを生成するものが必要です。

<a href=\"/mycontroller/myaction\">Action!</a>

これはescape_javascript機能です それは返された文字列がjavascriptを "中断"しないことを保証します。 あなたがそれを使うなら、あなたは望ましい出力を得るでしょう:

$("#reviews").append("<a href=\"/mycontroller/myaction\">Action!</a>")

よろしく!

Question

私はこのRailscastのエピソードを見ていて、なぜescape_javascriptの呼び出しが必要なのか不思議です:

$("#reviews").append("<%= escape_javascript(render(:partial => @review)) %>");

escape_javascriptとは何ですか?

Railsドキュメントによると:

エスケープ_Javascript(javascript)

JavaScriptセグメントのエスケープ・キャリア・リターンと一重引用符と二重引用符。

しかし、それは私にはあまり意味がありません。




hereでソースを見ると、はるかに明確になります。

この関数は、次の2つを実行します。

  1. これは、入力文字列の文字をJS_ESCAPE_MAP定義された文字でJS_ESCAPE_MAP

    これの目的は、javascriptコードが埋め込まれている外側の文字列と干渉することなく正しくシリアライズされるようにすることです。 たとえば、JavaScript文字列を二重引用符で囲んだ場合、コードが改行されないようにするには、文字列リテラル内のすべての引用符を一重引用符で囲む必要があります。

  2. この関数は、結果の文字列がhtmlセーフであるかどうかもチェックします。 そうでなければ、文字列がhtmlセーフであることを確認するために必要なエスケープを行い、結果を返します。

escape_javascriptを使用している場合、通常は別の文字列または既存のHTMLに動的に埋め込まれます。 これを実行してもページ全体がレンダリングされないことを確認する必要があります。

このレスポンスのいくつかの側面は他のレスポンスで指摘されていましたが、javascriptエスケープとhtmlエスケープの違いを含めてすべてのアイテムをまとめてみたかったのです。 また、いくつかの応答は、この機能がスクリプトの注入を回避するのに役立つことを暗示しています。 私はそれがこの機能の目的だとは思わない。 たとえば、あなたのレビューに警告がある場合( 'hi there')、それをノードに追加するだけではポップアップは起動しません。 ページの読み込みやその他のイベントによってトリガされる関数内に埋め込みません。 単にあなたのhtmlの一部としてアラート( 'hi there')を持っていても、それがjavascriptとして実行されるわけではありません。

それは私がスクリプトの注入が不可能であることを否定していないと言いました。 しかし、それを避けるためには、ユーザデータを取得してデータベースに保存する際に措置を講じる必要があります。 提供している関数と例は、既に保存されている情報のレンダリングに関連しています。

私はこれがあなたの質問に役立つことを願っています。




Links