web-dev-qa-db-ja.com

JavaScriptでHTMLをエスケープするにはどうすればよいですか?

与えられたテキスト

_<b>This is some text</b>
_

これを自分のページに書き込んで、次のように表示したいと思います。

_<b>This is some text</b>_

これは好きじゃない

これはテキストです

escape("<b>This is some text</b>")を使用すると、Firefoxでこの素敵な宝石が得られます

_%3Cb%3EThis%20is%20some%20text%3C/b%3E
_

私が求めているものを免れません。何か案は?

25
Micah

これはあなたのために働くはずです: http://blog.nickburwell.com/2011/02/escape-html-tags-in-javascript.html

function escapeHTML( string )
{
    var pre = document.createElement('pre');
    var text = document.createTextNode( string );
    pre.appendChild(text);
    return pre.innerHTML;
}

セキュリティ警告

関数は一重引用符と二重引用符をエスケープしません。誤ったコンテキストで使用すると、XSSが発生する可能性があります。例えば:

 var userWebsite = '" onmouseover="alert(\'gotcha\')" "';
 var profileLink = '<a href="' + escapeHtml(userWebsite) + '">Bob</a>';
 var div = document.getElemenetById('target');
 div.innerHtml = profileLink;
 // <a href="" onmouseover="alert('gotcha')" "">Bob</a>

このケースを指摘してくれた buffer に感謝します。 このブログ投稿 から抜粋したスニペット。

58
limc

私はこれをやった:

function escapeHTML(s) { 
    return s.replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');
}
29
Michele Bosi

HTML DOMドキュメントが利用できる状況では@limcの回答が好きです。

Node.jsなどの非HTML DOMドキュメント環境に対する@Michele Bosiと@Paoloの回答が好きです。

@Michael Bosiの答えは、replaceを4回呼び出す必要をなくすことで最適化できます。

function escape(s) {
    let lookup = {
        '&': "&amp;",
        '"': "&quot;",
        '<': "&lt;",
        '>': "&gt;"
    };
    return s.replace( /[&"<>]/g, (c) => lookup[c] );
}
console.log(escape("<b>This is some text.</b>"));

@Paoloの範囲テストは、適切に選択された正規表現を使用して最適化でき、forループは、置換関数を使用して削除できます。

function escape(s) {
    return s.replace(
        /[^0-9A-Za-z ]/g,
        c => "&#" + c.charCodeAt(0) + ";"
    );
}
console.log(escape("<b>This is some text</b>"));

@Paoloが示したように、この戦略はより多くのシナリオで機能します。

20
Stephen Quan

伝統的な脱出

XHTMLを使用している場合は、CDATAセクションを使用する必要があります。これらはHTMLでも使用できますが、HTMLはそれほど厳密ではありません。

文字列定数を分割して、このコードがCDATAブロック内のXHTMLでインラインで機能するようにしました。 JavaScriptを個別のファイルとして調達する場合は、それを気にする必要はありません。 areインラインJavaScriptでXHTMLを使用する場合、needを使用してコードをCDATAブロックで囲む必要があります。そうしないと機能しません。奇妙な微妙なエラーに遭遇します。

function htmlentities(text) {
    var escaped = text.replace(/\]\]>/g, ']]' + '>]]&gt;<' + '![CDATA[');
    return '<' + '![CDATA[' + escaped + ']]' + '>';
}

DOMテキストノード

テキストをエスケープする「適切な」方法は、DOM関数document.createTextNodeを使用することです。これは実際にはテキストをエスケープしません。本質的に解析されないテキスト要素を作成するようブラウザに指示するだけです。ただし、このメソッドを機能させるにはDOMを使用する必要があります。つまり、appendChildプロパティなどとは対照的に、innerHTMLなどのメソッドを使用する必要があります。これにより、ID an-elementの要素に(X)HTMLとして解析されないテキストが入力されます。

var textNode = document.createTextNode("<strong>This won't be bold.  The tags " +
    "will be visible.</strong>");
document.getElementById('an-element').appendChild(textNode);

jQuery DOMラッパー

jQueryはcreateTextNodeという名前のtextという便利なラッパーを提供します。とても便利です。 jQueryを使用した同じ機能は次のとおりです。

$('#an-element').text("<strong>This won't be bold.  The tags will be " +
    "visible.</strong>");
3
Zenexer

山かっこをHTMLエンティティに置き換える関数を次に示します。他の文字も含めるように拡張することもできます。

function htmlEntities( html ) {
    html = html.replace( /[<>]/g, function( match ) {
        if( match === '<' ) return '&lt;';
        else return '&gt;';
    });
    return html;
}

console.log( htmlEntities( '<b>replaced</b>' ) ); // &lt;b&gt;replaced&lt;/b&gt;
2
meouw

文字列内のすべての文字をエンコードできます。

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

または、次のように、心配するメインキャラクター(&、inebreak、<、>、 "、 ')をターゲットにします。

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

test.value=encode('Encode HTML entities!\n\n"Safe" escape <script id=\'\'> & useful in <pre> tags!');

testing.innerHTML=test.value;

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows="9" cols="55"></textarea>

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

これを試してください JavaScriptのHTMLエンティティ

function htmlEntities(str) {
    return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}
2
Headshota

&#nnn;az AZ 0-を除く)表記ですべての文字をエスケープする次の関数を使用します9およびスペース

_function Escape( s )
{
    var h,
        i,
        n,
        c;

    n = s.length;
    h = '';

    for( i = 0; i < n; i++ )
    {
        c = s.charCodeAt( i );
        if( ( c >= 48 && c <= 57 ) 
          ||( c >= 65 && c <= 90 ) 
          ||( c >= 97 && c <=122 )
          ||( c == 32 ) )
        {
            h += String.fromCharCode( c );
        }
        else
        {
            h += '&#' + c + ';';
        }
    }

    return h;
}
_

例:

Escape('<b>This is some text</b>')

戻り値

_&#60;b&#62;This is some text&#60;&#47;b&#62;_

関数は、コードインジェクション攻撃の証拠、Unicodeの証拠、純粋なJavaScriptです。

このアプローチは、DOMテキストノードを作成するアプローチよりも約50倍遅いですが、関数は100〜150ミリ秒で100万(1,000,000)文字の文字列をエスケープします。

(2011年初頭のMacBook Pro-Safari 9-Mavericksでテスト済み)

1
Paolo