641

jQueryの文字列から HTML をエスケープする簡単な方法を知っている人はいますか? 任意の文字列を渡して、HTML ページに表示するために適切にエスケープできるようにする必要があります (JavaScript/HTML インジェクション攻撃を防ぎます)。これを行うためにjQueryを拡張することは可能だと確信していますが、現時点ではこれを達成するためのフレームワークについて十分に知りません.

4

27 に答える 27

643

mustache.js からのソリューションもあります

var entityMap = {
  '&': '&',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  "'": '&#39;',
  '/': '&#x2F;',
  '`': '&#x60;',
  '=': '&#x3D;'
};

function escapeHtml (string) {
  return String(string).replace(/[&<>"'`=\/]/g, function (s) {
    return entityMap[s];
  });
}
于 2012-08-20T08:21:05.680 に答える
468

jQueryを使用しているため、要素のtextプロパティを設定するだけです。

// before:
// <div class="someClass">text</div>
var someHtmlString = "<script>alert('hi!');</script>";

// set a DIV's text:
$("div.someClass").text(someHtmlString);
// after: 
// <div class="someClass">&lt;script&gt;alert('hi!');&lt;/script&gt;</div>

// get the text in a string:
var escaped = $("<div>").text(someHtmlString).html();
// value: 
// &lt;script&gt;alert('hi!');&lt;/script&gt;
于 2008-08-24T17:22:15.480 に答える
185
$('<div/>').text('This is fun & stuff').html(); // "This is fun &amp; stuff"

ソース: http://debuggable.com/posts/encode-html-entities-with-jquery:480f4dd6-13cc-4ce9-8071-4710cbdd56cb

于 2008-12-17T10:28:45.113 に答える
61

HTMLをエスケープする場合、本当に必要だと思うのは3つだけです。

html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");

ユースケースによっては、次のようなことも必要になる場合があり"ます&quot;。リストが十分に大きくなった場合は、配列を使用します。

var escaped = html;
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]]
for(var item in findReplace)
    escaped = escaped.replace(findReplace[item][0], findReplace[item][1]);

encodeURIComponent()HTMLではなくURLに対してのみエスケープします。

于 2008-08-24T05:54:49.160 に答える
40

アンダースコアを使用するのは簡単です:

_.escape(string) 

Underscoreは、ネイティブ js が提供しない多くの機能を提供するユーティリティ ライブラリです。アンダースコアと同じ API ですが、よりパフォーマンスが向上するように書き直されたlodashもあります。

于 2013-09-12T05:30:46.013 に答える
37

私はこのパーティーに遅刻したことを認識していますが、jQuery を必要としない非常に簡単な解決策があります。

escaped = new Option(unescaped).innerHTML;

編集:これは引用符をエスケープしません。引用符をエスケープする必要がある唯一のケースは、コンテンツが HTML 文字列内の属性にインラインで貼り付けられる場合です。これを行うことが良い設計になる場合を想像するのは難しいです。

編集 3: 最速の解決策については、上記の Saram の回答を確認してください。これが最短です。

于 2016-03-01T22:55:19.110 に答える
37

これを行う小さな関数を書きました。"&<およびのみをエスケープ>します (ただし、通常はそれだけで十分です)。1 つ .replace()だけを使用してすべての変換を行うという点で、以前に提案されたソリューションよりもわずかに洗練されています。(編集 2:コードの複雑さを軽減して、関数をさらに小さくきれいにします。元のコードに興味がある場合は、この回答の最後を参照してください。)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&<>]/g, function (a) {
        return { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' }[a];
    });
}

これは単純な Javascript であり、jQuery は使用されていません。

逃げること/'

mklementのコメントに応じて編集します。

上記の関数は、任意の文字を含むように簡単に拡張できます。エスケープする文字をさらに指定するには、正規表現の文字クラス (つまり 内) とオブジェクト/[...]/gのエントリの両方に挿入するだけです。chr編集2:同じ方法で、この関数も短縮されました。)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&'\/<>]/g, function (a) {
        return {
            '"': '&quot;', '&': '&amp;', "'": '&#39;',
            '/': '&#47;',  '<': '&lt;',  '>': '&gt;'
        }[a];
    });
}

上記の&#39;for アポストロフィの使用に注意してください (&apos;代わりにシンボリック エンティティが使用されている可能性があります。これは XML で定義されていますが、もともと HTML 仕様に含まれていなかったため、すべてのブラウザーでサポートされていない可能性があります。参照: HTML 文字エンコーディングに関するウィキペディアの記事)。また、16 進数を使用するよりも 10 進数エンティティを使用する方が広くサポートされていることをどこかで読んだことを思い出しますが、今のところそのソースを見つけることができないようです。(そして、16 進数のエンティティをサポートしていないブラウザーは多くありません。)

注:/エスケープ文字のリストにandを追加する'ことは、HTML では特別な意味を持たず、エスケープする必要がないため、それほど有用ではありません。

オリジナルescapeHtml機能

編集 2:元の関数は変数 ( chr) を使用して、コールバックに必要なオブジェクトを格納しました.replace()。この変数には、スコープを設定するための追加の無名関数も必要であり、関数が (不必要に) 少し大きく複雑になりました。

var escapeHtml = (function () {
    'use strict';
    var chr = { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' };
    return function (text) {
        return text.replace(/[\"&<>]/g, function (a) { return chr[a]; });
    };
}());

2 つのバージョンのどちらが速いかはテストしていません。その場合は、ここに情報とリンクを自由に追加してください。

于 2012-11-14T00:39:33.710 に答える
30

最後のテストの後、最速で完全にクロス ブラウザー互換のネイティブ javaScript (DOM) ソリューションをお勧めします。

function HTMLescape(html){
    return document.createElement('div')
        .appendChild(document.createTextNode(html))
        .parentNode
        .innerHTML
}

何度も繰り返すと、一度準備された変数でそれを行うことができます:

//prepare variables
var DOMtext = document.createTextNode("test");
var DOMnative = document.createElement("span");
DOMnative.appendChild(DOMtext);

//main work for each case
function HTMLescape(html){
  DOMtext.nodeValue = html;
  return DOMnative.innerHTML
}

私の最終的なパフォーマンス比較を見てください(スタックの質問)。

于 2013-07-09T10:44:35.483 に答える
24

Underscore.string lib を試してみてください。jQuery で動作します。

_.str.escapeHTML('<div>Blah blah blah</div>')

出力:

'&lt;div&gt;Blah blah blah&lt;/div&gt;'
于 2012-08-20T07:36:13.763 に答える
17

escape()unescape()HTML ではなく、URL の文字列をエンコード/デコードすることを目的としています。

実際、私は次のスニペットを使用して、フレームワークを必要としないトリックを実行します。

var escapedHtml = html.replace(/&/g, '&amp;')
                      .replace(/>/g, '&gt;')
                      .replace(/</g, '&lt;')
                      .replace(/"/g, '&quot;')
                      .replace(/'/g, '&apos;');
于 2012-05-25T12:39:21.180 に答える
15

escapeHTML()文字列オブジェクトにメソッドを追加するmustache.jsの例を拡張しました。

var __entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
};

String.prototype.escapeHTML = function() {
    return String(this).replace(/[&<>"'\/]/g, function (s) {
        return __entityMap[s];
    });
}

そうすれば非常に使いやすいです"Some <text>, more Text&Text".escapeHTML()

于 2012-11-22T10:20:19.583 に答える
11

underscore.js がある場合は、以下を使用します_.escape(上記の jQuery メソッドよりも効率的です)。

_.escape('Curly, Larry & Moe'); // returns: Curly, Larry &amp; Moe
于 2014-09-04T17:15:18.663 に答える
5

正規表現ルートを使用している場合、上記の tghw の例にはエラーがあります。

<!-- WON'T WORK -  item[0] is an index, not an item -->

var escaped = html; 
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g,"&gt;"], [/"/g,
"&quot;"]]

for(var item in findReplace) {
     escaped = escaped.replace(item[0], item[1]);   
}


<!-- WORKS - findReplace[item[]] correctly references contents -->

var escaped = html;
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]]

for(var item in findReplace) {
     escaped = escaped.replace(findReplace[item[0]], findReplace[item[1]]);
}
于 2011-05-21T21:18:27.783 に答える
5

これは良い安全な例です...

function escapeHtml(str) {
    if (typeof(str) == "string"){
        try{
            var newStr = "";
            var nextCode = 0;
            for (var i = 0;i < str.length;i++){
                nextCode = str.charCodeAt(i);
                if (nextCode > 0 && nextCode < 128){
                    newStr += "&#"+nextCode+";";
                }
                else{
                    newStr += "?";
                }
             }
             return newStr;
        }
        catch(err){
        }
    }
    else{
        return str;
    }
}
于 2012-10-31T01:08:05.763 に答える
3

JQUERYを必要としない2つの簡単な方法...

次のように、文字列内のすべての文字をエンコードできます。

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

または、メイン キャラクターを対象にして&、 、改行、、<などを心配するだけです。>"'

function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

var myString='Encode HTML entities!\n"Safe" escape <script></'+'script> & other tags!';

test.value=encode(myString);

testing.innerHTML=encode(myString);

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<p><b>What JavaScript Generated:</b></p>

<textarea id=test rows="3" cols="55"></textarea>

<p><b>What It Renders Too In HTML:</b></p>

<div id="testing">www.WHAK.com</div>

于 2015-07-26T14:02:43.757 に答える
2
(function(undefined){
    var charsToReplace = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;'
    };

    var replaceReg = new RegExp("[" + Object.keys(charsToReplace).join("") + "]", "g");
    var replaceFn = function(tag){ return charsToReplace[tag] || tag; };

    var replaceRegF = function(replaceMap) {
        return (new RegExp("[" + Object.keys(charsToReplace).concat(Object.keys(replaceMap)).join("") + "]", "gi"));
    };
    var replaceFnF = function(replaceMap) {
        return function(tag){ return replaceMap[tag] || charsToReplace[tag] || tag; };
    };

    String.prototype.htmlEscape = function(replaceMap) {
        if (replaceMap === undefined) return this.replace(replaceReg, replaceFn);
        return this.replace(replaceRegF(replaceMap), replaceFnF(replaceMap));
    };
})();

グローバル変数なし、メモリの最適化。使用法:

"some<tag>and&symbol©".htmlEscape({'©': '&copy;'})

結果は次のとおりです。

"some&lt;tag&gt;and&amp;symbol&copy;"
于 2013-05-13T11:21:59.030 に答える
0
function htmlEscape(str) {
    var stringval="";
    $.each(str, function (i, element) {
        alert(element);
        stringval += element
            .replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(' ', '-')
            .replace('?', '-')
            .replace(':', '-')
            .replace('|', '-')
            .replace('.', '-');
    });
    alert(stringval);
    return String(stringval);
}
于 2012-06-27T15:15:00.270 に答える
0
function htmlDecode(t){
   if (t) return $('<div />').html(t).text();
}

魅力のように機能します

于 2013-06-03T02:48:33.027 に答える
0

速度が最適化されたバージョン:

function escapeHtml(s) {
   let out = "";
   let p2 = 0;
   for (let p = 0; p < s.length; p++) {
      let r;
      switch (s.charCodeAt(p)) {
         case 34: r = "&quot;"; break;  // "
         case 38: r = "&amp;" ; break;  // &
         case 39: r = "&#39;" ; break;  // '
         case 60: r = '&lt;'  ; break;  // <
         case 62: r = '&gt;'  ; break;  // >
         default: continue;
      }
      if (p2 < p) {
         out += s.substring(p2, p);
      }
      out += r;
      p2 = p + 1;
   }
   if (p2 == 0) {
      return s;
   }
   if (p2 < s.length) {
      out += s.substring(p2);
   }
   return out;
}

const s = "Hello <World>!";
document.write(escapeHtml(s));
console.log(escapeHtml(s));

于 2020-12-27T03:12:14.063 に答える
-2

この回答はjQueryと通常のJSメソッドを提供しますが、これはDOMを使用しないで最短です:

unescape(escape("It's > 20% less complicated this way."))

エスケープされた文字列:It%27s%20%3E%2020%25%20less%20complicated%20this%20way.

エスケープされたスペースが気になる場合は、次を試してください。

unescape(escape("It's > 20% less complicated this way.").replace(/%20/g, " "))

エスケープされた文字列:It%27s %3E 20%25 less complicated this way.

残念ながら、このescape()関数はJavaScript バージョン 1.5 で廃止されましたencodeURI()またはencodeURIComponent()は代替ですが、 を無視する'ため、コードの最後の行は次のようになります。

decodeURI(encodeURI("It's > 20% less complicated this way.").replace(/%20/g, " ").replace("'", '%27'))

すべての主要なブラウザーはまだショート コードをサポートしており、古い Web サイトの数を考えると、すぐに変更されるとは思えません。

于 2012-09-18T08:45:58.860 に答える
-2

この情報をデータベースに保存する場合、クライアント側のスクリプトを使用して HTML をエスケープするのは間違っています。これはサーバーで行う必要があります。そうしないと、XSS 保護を簡単にバイパスできます。

私の主張を明確にするために、回答の1つを使用した例を次に示します。

関数 escapeHtml を使用してブログのコメントから Html をエスケープし、それをサーバーに投稿するとします。

var entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
  };

  function escapeHtml(string) {
    return String(string).replace(/[&<>"'\/]/g, function (s) {
      return entityMap[s];
    });
  }

ユーザーは次のことができます。

  • POST リクエスト パラメータを編集し、コメントを JavaScript コードに置き換えます。
  • ブラウザー コンソールを使用して、escapeHtml 関数を上書きします。

ユーザーがこのスニペットをコンソールに貼り付けると、XSS 検証がバイパスされます。

function escapeHtml(string){
   return string
}
于 2015-03-06T18:55:24.570 に答える
-2

再エスケープを防止しない場合、すべてのソリューションは役に立ちません。たとえば、ほとんどのソリューションは にエスケープ&し続け&amp;ます。

escapeHtml = function (s) {
    return s ? s.replace(
        /[&<>'"]/g,
        function (c, offset, str) {
            if (c === "&") {
                var substr = str.substring(offset, offset + 6);
                if (/&(amp|lt|gt|apos|quot);/.test(substr)) {
                    // already escaped, do not re-escape
                    return c;
                }
            }
            return "&" + {
                "&": "amp",
                "<": "lt",
                ">": "gt",
                "'": "apos",
                '"': "quot"
            }[c] + ";";
        }
    ) : "";
};
于 2015-05-26T19:52:33.117 に答える