2009-10-25 34 views
110

私はthis Railscast episodeを見て、escape_javascriptへの呼び出しが、ここで必要とされる理由は思ったんだけど:部分をレンダリングする前にescape_javascriptを使用するのはなぜですか?

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

escape_javascriptは何に使用されますか? the Rails docsによれば

escape_javascript(ジャバスクリプト)

エスケープキャリア戻り、単一およびJavaScriptセグメントの 二重引用符。

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

+19

参考になった回答は正解ではありません。 Kikitoは – Steve

答えて

1

ブラウザを実際に実行するJavaScriptをユーザーが投稿しないようにするためですか?

+4

ですが、JavaScriptコードを渡してレンダリングしたいときはどうですか? – berto77

+0

ええ、実際はそれがフォーマット方法のほうです。ユーザーが自分のjavascriptを実行するのを妨げるものではありません。それを防ぐことはできません。 – Deviljho

+2

これは役に立ちません。代わりに[kikitoの答え](http://stackoverflow.com/a/1623813/703233)を参照してください。 – nitsas

8

悪意のあるコード(悪意のあるユーザー)は、エスケープされずに放置されると、ユーザーがアプリケーションを制御できるようになる可能性があります。レールの構文で

<% variable = '"); alert("hi there' %> 
$("#reviews").append("<%= variable %>"); 

本当に慣れていないが、あなたはvariableをエスケープしていない場合は、アラートボックスが表示されます、と私はそれが意図した動作であると思ういけない:

はこれを試してみてください。

327

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

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

ルビが生成するものは、二重引用符で囲んだjavascript文字列内に含める必要があります。<%= ... %>の前後に二重引用符があることに注意してください。

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

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

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

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

JavaScriptは二重引用符で囲まれた文字列をパラメータとして使用していたことを覚えていますか? <%= ... %>を部分的なコードに置き換えただけの場合は、問題があります。href=の直後に二重引用符があります。

<a href=\"/mycontroller/myaction\">Action!</a> 
: - :JavaScriptが有効ではありません、あなたは代わりに、これを生成何かが必要

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

この現象が発生しないためには、あなたの文字列がカットされていないので、あなたはエスケープこれらの特殊文字にしたいです

これは何ですか?escape_javascriptです。それは返された文字列がjavascriptを "中断"しないことを保証します。あなたがそれを使用する場合は、希望の出力を得るでしょう:

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

よろしく!

+4

本当に、非常に素晴らしい説明ありがとうございます。私たちは実際にjavascriptをエスケープするために実際に使用していないので、 'escape_javascript'を使用するのは誤解を招くようなものです。あなたは部分的にスクリプトタグを置くことができ、あなたが望むjavascriptを実行することができます。 – Steve

+12

@Steveは、javascriptを破らないように他のコード(例えばHTML)をエスケープすることが多いので、より良い名前は 'escape_for_javascript'でしょう。 – kikito

+13

'escape_javascript()'はもっと簡単なメソッドを持っています:単純な 'j()'(少なくともRails 4では)。 – mjnissim

7

あなたがソースhereを見れば、それがより明確になります。

この関数は、次の二つ実現:

  1. それはJS_ESCAPE_MAP

    この目的を確認することである

    で定義されたもの と入力文字列内の文字を置換しているJavaScriptコード埋め込まれている外側の文字列 に干渉することなく正しくシリアライズされています( )。あなたは二重引用符で javascriptの文字列を持っている場合たとえば、その後 文字列リテラルの中のすべての引用符が 破壊からコードを避けるために、単一引用符で囲む必要があります。

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

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

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

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

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

-3

レンダリング対象のjavascriptは実行されません

関連する問題