web-dev-qa-db-ja.com

onClickハンドラー内のJavaScriptコード内の文字列をエスケープするにはどうすればよいですか?

たぶん私はこれについて一生懸命考えているだけかもしれませんが、リンクのonClickハンドラー内のJavaScriptコードの文字列でどのエスケープを使用するかを理解するのに問題があります。例:

<a href="#" onclick="SelectSurveyItem('<%itemid%>', '<%itemname%>'); return false;">Select</a>

<%itemid%>および<%itemname%>は、テンプレートの置換が行われる場所です。私の問題は、アイテム名に単一引用符や二重引用符を含む任意の文字を含めることができることです。現在、単一引用符が含まれていると、JavaScriptコードが破損します。

私が最初に考えたのは、テンプレート言語の関数を使用して、引用符をエスケープするだけのアイテム名をJavaScriptエスケープすることでした。それは、リンクのHTMLを壊す二重引用符を含む文字列の大文字小文字を修正しません。この問題は通常どのように対処されますか? onClickハンドラー全体をHTMLエスケープする必要がありますか?

もしそうなら、テンプレート言語のエスケープ関数は括弧、引用符、セミコロンもHTML化するので、それは本当に奇妙に見えるでしょう...

このリンクは検索結果ページのすべての結果に対して生成されるため、JavaScriptタグ内に個別のメソッドを作成することはできません。結果ごとに1つ生成する必要があるためです。

また、私が働いている会社で自社開発したテンプレートエンジンを使用しているため、ツールキット固有のソリューションは役に立たないでしょう。

64
rmeador

JavaScriptでは、単一引用符を「\ x27」として、二重引用符を「\ x22」としてエンコードできます。したがって、このメソッドを使用すると、JavaScript文字列リテラルの(二重または単一)引用符の内側にいると、文字列の引用が「ブレイクアウト」する恐れなく、免責で\ x27\x22を使用できます。

\ xXXは文字<127、および\ uXXXXは nicode であるため、この知識があれば、堅牢なJSEncodeを作成できます通常のホワイトリストに含まれないすべての文字に対する関数。

例えば、

<a href="#" onclick="SelectSurveyItem('<% JSEncode(itemid) %>', '<% JSEncode(itemname) %>'); return false;">Select</a>
78
Duncan Smart

サーバー側の言語に応じて、次のいずれかを使用できます。

.NET 4.0

string result = System.Web.HttpUtility.JavaScriptStringEncode("jsString")

Java

import org.Apache.commons.lang.StringEscapeUtils;
...

String result = StringEscapeUtils.escapeJavaScript(jsString);

Python

import json
result = json.dumps(jsString)

PHP

$result = strtr($jsString, array('\\' => '\\\\', "'" => "\\'", '"' => '\\"', 
                                 "\r" => '\\r', "\n" => '\\n' ));

Ruby on Rails

<%= escape_javascript(jsString) %>
20

パラメーター<%itemid%>および<%itemname%>のそれぞれに1つずつ隠されたスパンを使用し、それらの値をそれらの内部に書き込みます。

たとえば、<%itemid%>のスパンは<span id='itemid' style='display:none'><%itemid%></span>のように見え、javascript関数ではSelectSurveyItemでこれらのスパンのinnerHTMLから引数を選択します。

10
Shyam

HTMLで文字列リテラルの使用を避け、JavaScriptを使用してJavaScriptイベントをバインドしてください。

また、本当に自分が何をしているかを知らない限り、 'href =#'を避けてください。強制的なミドルクリッカー(タブオープナー)の使いやすさを損ないます。

<a id="tehbutton" href="somewhereToGoWithoutWorkingJavascript.com">Select</a>

私が選んだJavaScriptライブラリはたまたまjQueryです。

<script type="text/javascript">//<!-- <![CDATA[
jQuery(function($){
   $("#tehbutton").click(function(){
        SelectSurveyItem('<%itemid%>', '<%itemname%>');
        return false;
   });
});
//]]>--></script>

そのようなリンクのリストをレンダリングしている場合、これを行うことができます。

<a id="link_1" href="foo">Bar</a>
<a id="link_2" href="foo2">Baz</a>

<script type="text/javascript">
   jQuery(function($){
        var l = [[1,'Bar'],[2,'Baz']];
        $(l).each(function(k,v){
           $("#link_" + v[0] ).click(function(){
                SelectSurveyItem(v[0],v[1]);
                return false;
           });
        });
   });
 </script>
9
Kent Fredric

HTML属性に入る場合は、HTMLエンコード(少なくとも:>から&gt;<から&ltおよび"から&quot;)it、and単一引用符をバックスラッシュでエスケープして、javascriptの引用に干渉しないようにします。

それを行う最良の方法は、テンプレートシステムを使用することです(必要に応じて拡張します)が、単純に2つのエスケープ/エンコード関数を作成し、そこに入力されるデータの両方をラップすることができます。

そして、はい、JavaScriptが含まれている場合でも、HTML属性のコンテンツ全体をHTMLエスケープすることは完全に(正確でさえ)有効です。

8
Dan

別の興味深い解決策は、これを行うことです。

<a href="#" itemid="<%itemid%>" itemname="<%itemname%>" onclick="SelectSurveyItem(this.itemid, this.itemname); return false;">Select</a>

次に、両方の変数に標準のHTMLエンコードを使用できます。JavaScriptの引用の余分な複雑さを心配する必要はありません。

はい、これはdoes厳密に無効なHTMLを作成します。ただし、それはis有効な手法であり、最新のすべてのブラウザーでサポートされています。

それが私の場合は、おそらく最初の提案に行き、値がHTMLエンコードされていることを確認しますandは単一引用符をエスケープします。

3
Dan

<head>セクションで個別の関数を宣言し、onClickメソッドでそれらを呼び出します。たくさんある場合は、それらに番号を付ける命名スキームを使用するか、onClicksに整数を渡し、関数に大きな太ったswitchステートメントを含めることができます。

1
moonshadow

JavaScriptエンコードを含む Microsoft Anti-XSS library を使用します。

1
blowdart

まず、onclickハンドラーが次のように設定されていると、より簡単になります。

<a id="someLinkId"href="#">Select</a>
<script type="text/javascript">
  document.getElementById("someLinkId").onClick = 
   function() {
      SelectSurveyItem('<%itemid%>', '<%itemname%>'); return false;
    };

</script>

次に、itemidとitemnameをJavaScript用にエスケープする必要があります(つまり、"\"などになります)。

サーバー側でJavaを使用している場合、jakartaのcommon-langのクラス StringEscapeUtils を見ることができます。独自の「escapeJavascript」メソッドを作成します。

1

私もこの問題に直面しています。一重引用符をエスケープされた二重引用符に変換するスクリプトを作成しました。これにより、HTMLが壊れることはありません。

function noQuote(text)
{
    var newtext = "";
    for (var i = 0; i < text.length; i++) {
        if (text[i] == "'") {
            newtext += "\"";
        }
        else {
            newtext += text[i];
        }
    }
    return newtext;
}
1

その優れたテンプレートエンジンには、「エスケープクォート」機能があります。私たち(また、私が働いている自家製)には、javascriptの引用符をエスケープする機能があります。どちらの場合でも、テンプレート変数には、必要に応じて_escまたは_js_escが追加されます。ユーザーが生成したコンテンツを、エスケープされていないブラウザ(IMHO)に出力しないでください。

0
livingtech

JavaScriptを使用して引用符をエスケープすることはできず、エスケープされた文字列から開始する必要があるという答えがここにあります。

したがって。 JavaScriptが文字列「Margeが「そうだ」とPeterに言った」を処理する方法はなく、スクリプトに提供する前にデータをクリーンアップする必要がありますか?

0
Steve Perks

私は同じ問題に直面し、トリッキーな方法でそれを解決しました。まず、グローバル変数v1、v2、およびv3を作成します。そして、onclickでインジケーター1、2、または3を送信し、機能チェックで1、2、3のv1、v2、v3を次のように配置します。

onclick="myfun(1)"
onclick="myfun(2)"
onclick="myfun(3)"

function myfun(var)
{
    if (var ==1)
        alert(v1);

    if (var ==2)
        alert(v2);

    if (var ==3)
        alert(v3);
}
0
AhmedGamal