回答:
セキュリティ上の注意:この回答(以下の元の形式で保持される)を使用すると、アプリケーションにXSSの脆弱性が生じる可能性があります。この答えは使用しないでください。この回答の脆弱性の説明についてはルカスカロの回答を読み、代わりにその回答またはマークアメリーの回答からのアプローチを使用してください。
実は、やってみて
var decoded = $("<div/>").html(encodedStr).text();
$("<div/>").html('<img src="http://www.google.com/images/logos/ps_logo2.png" onload=alert(1337)>')
。FirefoxまたはSafariでは、アラートが発生します。
str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/g, "")
または似たようなもの。
jQueryなし:
function decodeEntities(encodedString) {
var textArea = document.createElement('textarea');
textArea.innerHTML = encodedString;
return textArea.value;
}
console.log(decodeEntities('1 & 2')); // '1 & 2'
これは受け入れられた回答と同様に機能しますが、信頼できないユーザー入力で安全に使用できます。
マイク・サミュエルが指摘し、でこれを行う<div>
代わりに、<textarea>
信頼できないユーザの入力を持つことはあっても、XSSの脆弱性である<div>
DOMに追加されることはありません。
function decodeEntities(encodedString) {
var div = document.createElement('div');
div.innerHTML = encodedString;
return div.textContent;
}
// Shows an alert
decodeEntities('<img src="nonexistent_image" onerror="alert(1337)">')
ただし、の<textarea>
コンテンツが許可されているHTML要素がないため、aに対してこの攻撃を行うことはできません<textarea>
。その結果、「エンコードされた」文字列にまだ存在するHTMLタグは、ブラウザによって自動的にエンティティエンコードされます。
function decodeEntities(encodedString) {
var textArea = document.createElement('textarea');
textArea.innerHTML = encodedString;
return textArea.value;
}
// Safe, and returns the correct answer
console.log(decodeEntities('<img src="nonexistent_image" onerror="alert(1337)">'))
警告:この使用してjQueryの行う
.html()
と.val()
メソッドの代わりに使用する.innerHTML
と.value
、jQueryのいくつかのバージョンの安全性の低いもある*を使用する場合でもtextarea
。これは、古いバージョンのjQueryがに渡される文字列に含まれるスクリプトを意図的かつ明示的に評価するため.html()
です。したがって、次のようなコードはjQuery 1.8のアラートを示しています。
//<!-- CDATA
// Shows alert
$("<textarea>")
.html("<script>alert(1337);</script>")
.text();
//-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
* この脆弱性をキャッチしてくれたEru Penkmanに感謝します。
decodedString = textArea.value;
textArea.remove();
return decodedString;
if ('remove' in Element.prototype) textArea.remove();
$("<div />").html(string).text()
は、提供された文字列内の任意のJavaScriptを実行します。これが問題の原因であったと思われます。承認された回答はこれに更新する必要があります。
Mike Samuelが言ったように、安全でないため、jQuery.html()。text()を使用してHTMLエンティティをデコードしないでください。
代わりに、@ VyvITのコメントからMustache.jsやdecodeEntitiesなどのテンプレートレンダラーを使用してください。
Underscore.jsユーティリティベルトライブラリにはメソッドescape
とunescape
メソッドが付属していますが、ユーザー入力に対して安全ではありません。
unescape
今までにドキュメントに含まれています。
_.unescape("'")
結果は「&#39;」のみ 単一引用符の代わりに。示すように、私が欠けているか、アンダースコアHTMLエンティティコードにエスケープしていませんが、何かがある:w3schools.com/tags/ref_entities.asp
escape
そしてunescape
メソッドは...ユーザー入力に対して安全ではない」と言います。これはどういう意味ですか?それは私にはナンセンスのように聞こえますが、おそらく何かが足りないのです-明確にしていただけますか
_.unescape("<img src=fake onerror=alert('boo!')>")
(Chrome / FF / IEで)。ただし、アラートは表示されませんでした。コンソールで試してみただけでなく、JSファイルにも入れました。同じ結果。
テキストとHTMLのメソッドを混同していると思います。この例を見てください。要素の内部HTMLをテキストとして使用すると、デコードされたHTMLタグ(2番目のボタン)が表示されます。しかし、それらをHTMLとして使用すると、HTML形式のビュー(最初のボタン)が表示されます。
<div id="myDiv">
here is a <b>HTML</b> content.
</div>
<br />
<input value="Write as HTML" type="button" onclick="javascript:$('#resultDiv').html($('#myDiv').html());" />
<input value="Write as Text" type="button" onclick="javascript:$('#resultDiv').text($('#myDiv').html());" />
<br /><br />
<div id="resultDiv">
Results here !
</div>
最初のボタンの書き込み:これはHTMLコンテンツです。
2番目のボタンの書き込み:これは<B> HTML </ B>コンテンツです。
ちなみに、jQueryプラグインで見つけたプラグイン-HTMLのエンコードとデコードを行うHTMLのデコードとエンコードを確認できます。
あなたは使用することができ、彼から入手できる、ライブラリをhttps://github.com/mathiasbynens/he
例:
console.log(he.decode("Jörg & Jürgen rocked to & fro "));
// Logs "Jörg & Jürgen rocked to & fro"
私は、ライブラリーの作成者に、このライブラリーをクライアントサイドのコードで使用して、ここや他の回答で<textarea>
提供されているハックを支持する理由があるかどうかについて質問しました。彼はいくつかの可能な正当化を提供しました:
node.jsサーバーサイドを使用している場合、HTMLエンコード/デコード用のライブラリを使用すると、クライアントサイドとサーバーサイドの両方で機能する単一のソリューションが得られます。
一部のブラウザのエンティティデコードアルゴリズムにはバグがあるか、一部の名前付き文字参照のサポートがありません。たとえば、Internet Explorerは、改行しないスペース(
)を正しくデコードしてレンダリングしますが、DOM要素のinnerText
プロパティを介して改行しないスペースではなく通常のスペースとして報告し、<textarea>
ハックを解除します(マイナーな方法でのみです)。さらに、IE 8および9 は、HTML 5に追加された新しい名前付き文字参照をサポートしていません。彼の作成者は、http://mathias.html5.org/tests/htmlで名前付き文字参照サポートのテストもホストしています。 /名前付き文字参照/。IE 8では、1,000を超えるエラーが報告されます。
エンティティのデコードに関連するブラウザのバグから隔離したい場合、および/または名前付き文字参照の全範囲を処理できるようにしたい場合は、<textarea>
ハックを回避できません。彼のようなライブラリが必要になります。
彼はこの方法でハックが少なくなるように感じています。
エンコード:
$("<textarea/>").html('<a>').html(); // return '<a>'
デコード:
$("<textarea/>").html('<a>').val() // return '<a>'
使用する
myString = myString.replace( /\&/g, '&' );
JavaScriptにはエンティティを処理するためのネイティブライブラリがないため、サーバー側で行うのが最も簡単です。また、JavaScriptを拡張するさまざまなフレームワークの検索結果の上部近くには何も見つかりませんでした。
「JavaScript HTMLエンティティ」を検索すると、その目的のためにいくつかのライブラリが見つかるかもしれませんが、それらはおそらく上記のロジックを中心に構築されます-エンティティごとにエンティティを置き換えます。
HTMLボタンの値として、HTMLエンティティ文字(⇓)が必要でした。ブラウザの最初からHTMLコードが適切に見えます。
<input type="button" value="Embed & Share ⇓" id="share_button" />
次に、文字も表示するトグルを追加しました。これは私の解決策です
$("#share_button").toggle(
function(){
$("#share").slideDown();
$(this).attr("value", "Embed & Share " + $("<div>").html("⇑").text());
}
これにより、ボタンに再び⇓が表示されます。これが誰かの役に立つことを願っています。
"Embed & Share \u21d1"
)を使用する方が簡単"Embed & Share ⇑"
ですが、UTF-8(またはUTF-16、または⇑文字をサポートするその他のエンコーディング)でスクリプトを提供できる場合はさらに良いでしょう。DOM要素を使用してHTMLエンティティを解析し、任意のUnicode文字をJavaScript文字列にベイク処理することは、Rube Goldbergを誇りに思う賢明で創造的なアプローチですが、良い方法ではありません。Unicodeエスケープは、このユースケースを処理するための言語です。
HTMLエンティティのカスタム関数を作成する必要があります。
function htmlEntities(str) {
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g,'>').replace(/"/g, '"');
}
Stringクラスを拡張します。
String::decode = ->
$('<textarea />').html(this).text()
そしてメソッドとして使用します:
"<img src='myimage.jpg'>".decode()
これを試して :
var htmlEntities = "<script>alert('hello');</script>";
var htmlDecode =$.parseHTML(htmlEntities)[0]['wholeText'];
console.log(htmlDecode);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
parseHTMLはJqueryライブラリの関数であり、指定された文字列に関する詳細を含む配列を返します。
場合によっては文字列が大きいため、関数はコンテンツを多くのインデックスに分離します。
すべてのインデックスデータを取得するには、任意のインデックスに移動してから、「wholeText」というインデックスにアクセスする必要があります。
インデックス0を選択したのは、それがすべてのケースで機能するためです(小さいストリングまたは大きいストリング)。
まだ1つの問題があります:エスケープされた文字列は、入力値に割り当てられたときに読みやすく見えません
var string = _.escape("<img src=fake onerror=alert('boo!')>");
$('input').val(string);
例:https ://jsfiddle.net/kjpdwmqa/3/
escape
ではUnderscore.jsのメソッドを使用しています。また、コードサンプルがOPの問題をどのように解決するかについての説明もありません。
または、ライブラリもあります。
ここ、https://cdnjs.com/libraries/he
npm install he //using node.js
<script src="js/he.js"></script> //or from your javascript directory
使い方は次のとおりです...
//to encode text
he.encode('© Ande & Nonso® Company LImited 2018');
//to decode the
he.decode('© Ande & Nonso® Company Limited 2018');
乾杯。
jQueryでHTMLエンティティをデコードするには、次の関数を使用します。
function html_entity_decode(txt){
var randomID = Math.floor((Math.random()*100000)+1);
$('body').append('<div id="random'+randomID+'"></div>');
$('#random'+randomID).html(txt);
var entity_decoded = $('#random'+randomID).html();
$('#random'+randomID).remove();
return entity_decoded;
}
使い方:
JavaScript:
var txtEncoded = "á é í ó ú";
$('#some-id').val(html_entity_decode(txtEncoded));
HTML:
<input id="some-id" type="text" />
最も簡単な方法は、クラスセレクターを要素に設定し、次のコードを使用することです。
$(function(){
$('.classSelector').each(function(a, b){
$(b).html($(b).text());
});
});
もう何も必要ありません!
私はこの問題を抱えていて、この明確な解決策を見つけ、それはうまく機能しました。