jQuery를 사용하여 HTML 엔터티를 디코딩하는 방법은 무엇입니까?


답변:


437

보안 정보 : 이 답변을 사용하면 (아래의 원래 형태로 유지됨 ) 응용 프로그램에 XSS 취약점이 발생할 수 있습니다 . 이 답변을 사용해서는 안됩니다. 이 답변의 취약점에 대한 설명은 lucascaro의 답변 을 읽고 대신 해당 답변 또는 Mark Amery의 답변을 사용하십시오.

실제로 시도해보십시오

var decoded = $("<div/>").html(encodedStr).text();

175
마십시오 하지 신뢰할 수없는 입력이 작업을 수행. 노드가 DOM에 연결되지 않은 경우에도 많은 브라우저가 이미지를로드하고 관련 이벤트를 발생시킵니다. 실행 해보십시오 $("<div/>").html('<img src="http://www.google.com/images/logos/ps_logo2.png" onload=alert(1337)>'). Firefox 또는 Safari에서는 경고가 발생합니다.
Mike Samuel

@Mike, 대신 무엇을 추천 하시겠습니까? 대체 할 내용을 모른다면
.replace

7
@ekkis, 엔터티를 디코딩하기 전에 태그를 제거해야합니다. str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/g, "")또는 비슷한 것.
Mike Samuel

2
입력에서 대부분의 HTML 태그 (Mike 제공)를 제거하는 더 나은 구현 (제 의견으로는)은 비슷한 질문에 대한 답변 입니다. 또한 jQuery의 오버 헤드가 없으므로 다른 환경에 매우 적합합니다.
Robert K

6
@MichaelStum 여기에서 편집하면 Mike Samuel의 의견과 가장 높은 투표를받은 답변이 모두 무효화 되었으며 모든 jQuery 버전에 대한 XSS 취약성실제로 수정하지 않고 (아래 답변 참조). 이 답변에 보안 경고를 추가하는 것이 합리적입니다 (그리고 그렇게하겠습니다). 실제로 보안 허점을 고치는 데 실패 하면서이 페이지의 다른 토론을 무의미하게 렌더링하는 것은 아닙니다!
Mark Amery

211

jQuery없이 :

function decodeEntities(encodedString) {
  var textArea = document.createElement('textarea');
  textArea.innerHTML = encodedString;
  return textArea.value;
}

console.log(decodeEntities('1 &amp; 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 요소가 없기 때문에이 공격은 불가능합니다 <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 에게 감사 합니다.


6
값을 추출한 후 텍스트 영역을 삭제하는 것이 좋습니다.decodedString = textArea.value; textArea.remove(); return decodedString;
Werner

2
또는 자바 스크립트 버전이 실제로 remove ()를 지원하는 경우에만 :if ('remove' in Element.prototype) textArea.remove();
Werner

6
@Werner 함수가 종료 되 자마자 참조를 보유한 변수가 더 이상 없으므로 가비지 수집기 에서 자동으로 제거합니다 .
user2428118

버튼 클릭의 코드 숨김에서 .NET과 함께 이것을 사용하고 있으며 어떤 이유로 받아 들인 대답으로 인해 포스트 백이 발생했습니다. 이 답변은 그렇지 않았으므로 이것이 최선의 답변입니다. 감사!
Snailer

@Snailer $("<div />").html(string).text() 는 제공된 문자열에서 모든 자바 스크립트를 실행하므로 문제의 원인이 의심됩니다. 수락 된 답변은이 답변으로 업데이트되어야합니다.
jbowman

80

Mike Samuel이 말했듯이 jQuery.html (). text ()를 사용하여 HTML 엔티티가 안전하지 않기 때문에 디코딩하지 마십시오.

대신 @VyvIT의 의견에서 Mustache.js 또는 decodeEntities 와 같은 템플릿 렌더러를 사용하십시오 .

Underscore.js 유틸리티 벨트 라이브러리는 escapeunescape메소드 와 함께 제공 되지만 사용자 입력에 안전하지 않습니다.

_. 탈출 (문자열)

_.unescape (문자열)


2
이것은 실제로 더 많은지지를받을 가치가 있습니다! 확실히 내가 선호하는 솔루션. 그들은 unescape지금까지 문서에 포함 했습니다.
치명적인 기타

5
_.unescape("&#39;")결과는 "& # 39;"입니다. 작은 따옴표 대신. 그림과 같이 내가 부족 또는 밑줄 HTML 엔티티 코드를 탈출하지 않는 뭔가는 다음과 같습니다 w3schools.com/tags/ref_entities.asp
제이슨 Axelson

6
github의 버그는 "수정되지 않음"으로 닫혔습니다. 즉,이 솔루션은 작동하지 않으며 작동하지 않습니다.
Igor Chubin

3
Underscore의 " escapeunescape메소드 ...는 사용자 입력에 안전하지 않습니다"라고 말합니다 . 이게 무슨 뜻이야? 그것은 나에게 말도 안되는 것처럼 들리지만, 아마도 뭔가 빠진 것 같습니다.
Mark Amery

2
@VyvIT 시도 _.unescape("&lt;img src=fake onerror=alert('boo!')&gt;")(Chrome / FF / IE). 그러나 경고가 표시 되지 않았습니다. 콘솔에서 시도하고 JS 파일에도 넣으십시오. 같은 결과입니다.
Vivek Athalye

28

텍스트와 HTML 메소드를 혼동하고 있다고 생각합니다. 이 예제를 보면 요소의 내부 HTML을 텍스트로 사용하면 디코딩 된 HTML 태그 (두 번째 버튼)가 표시됩니다. 그러나 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());" />
&nbsp;&nbsp;
<input value="Write as Text" type="button" onclick="javascript:$('#resultDiv').text($('#myDiv').html());" />
<br /><br />
<div id="resultDiv">
    Results here !
</div>

: 첫 번째 단추를 기록 여기에있다 HTML의 내용.

두 번째 버튼 쓰기 : <B> HTML </ B> 콘텐츠입니다.

그건 그렇고, jQuery 플러그인 에서 찾은 플러그인 -HTML 문자열을 인코딩하고 디코딩 하는 HTML 디코딩 및 인코딩 .


26

질문은 'with jQuery'에 의해 제한되지만 여기에 가장 적합한 답변에 제공된 jQuery 코드는 다음을 수행한다는 것을 아는 데 도움이 될 수 있습니다 ... 이는 jQuery와 함께 또는없이 작동합니다.

function decodeEntities(input) {
  var y = document.createElement('textarea');
  y.innerHTML = input;
  return y.value;
}

20

당신은 사용할 수 있습니다 그가 에서 라이브러리를 사용할 수를 https://github.com/mathiasbynens/he

예:

console.log(he.decode("J&#246;rg &amp J&#xFC;rgen rocked to &amp; fro "));
// Logs "Jörg & Jürgen rocked to & fro"

나는 도서관의 저자 도전 의 찬성 클라이언트 측 코드에서이 라이브러리를 사용하는 어떤 이유가 여부의 문제에 <textarea>제공 해킹 다른 답변 여기에 다른 곳에서. 그는 몇 가지 정당성을 제시했다.

  • node.js 서버 측을 사용하는 경우 HTML 인코딩 / 디코딩을위한 라이브러리를 사용하면 클라이언트 측과 서버 측 모두에서 작동하는 단일 솔루션이 제공됩니다.

  • 일부 브라우저의 엔티티 디코딩 알고리즘에 버그가 있거나 일부 명명 된 문자 참조에 대한 지원이 없습니다 . 예를 들어 Internet Explorer는 깨지지 않는 공백 ( &nbsp;)을 올바르게 디코딩하고 렌더링 하지만 DOM 요소의 innerText속성을 통해 나누지 않는 공백 대신 일반 공백으로보고 하여<textarea> 해킹을 (소량이지만). 또한, IE 8, 9는 단순히 지원하지 않는 의 저자 HTML 5에 추가 된 새로운라는 문자 참조의 그는 또한에 이름을 문자 참조 지원의 테스트를 호스팅 http://mathias.html5.org/tests/html을 / named-character-references / . IE 8에서는 1,000 개가 넘는 오류를보고합니다.

    엔터티 디코딩과 관련된 브라우저 버그로부터 격리되고 /하거나 전체 범위의 명명 된 문자 참조를 처리하려면 <textarea>해킹을 피할 수 없습니다 . 와 같은 도서관이 필요합니다 .

  • 그는 이런 식으로 일을하는 것이 덜 해킹 된 것처럼 느낍니다.


4
+1 jQuery는 모든 것에 대한 해결책이 아닙니다. 작업에 적합한 도구를 사용하십시오.
Mathias Bynens

HTML 엔터티를 디코딩하는 가장 좋은 방법입니다. 중 하나를 사용 innerHTML을 (이것과 비슷한 질문에) 모든 다른 답변 (새 HTML 요소, 프로세스 HTML 코드를 만든 다음 그 요소의 innerHTML을을 구 이것은 당신이, 아주 조심하지 않으면 XSS 공격에 취약 할 수 있습니다 더 참조 ), 또는 Underscore.js unescape 또는 Lodash unescape 메소드를 사용하여 둘 다 불완전합니다 (몇몇 HTML 엔티티에서만 작동 함). 그는 도서관이 가장 완전하고 안전한 옵션입니다!
ands

18

인코딩 :

$("<textarea/>").html('<a>').html();      // return '&lt;a&gt'

풀다:

$("<textarea/>").html('&lt;a&gt').val()   // return '<a>'

3
이미 작동하는 답변이 있으며 거의 ​​동일합니다. 우리는 중복 답변이 필요하지 않습니다
markasoftware

4
이것이 정답입니다. 톰의 답변은 DIV 요소를 사용하여 해당 답변을 XSS에 취약하게 만듭니다.
Francisco Hodge

2
이것은 명확성을위한 최선의 대답입니다.
Dan Randolph

4

사용하다

myString = myString.replace( /\&amp;/g, '&' );

JavaScript에는 엔티티 처리를위한 기본 라이브러리가 없기 때문에 서버 측에서 수행하는 것이 가장 쉽습니다. 또한 JavaScript를 확장하는 다양한 프레임 워크에 대한 검색 결과에서 가장 가까운 검색 결과를 찾지 못했습니다.

"자바 스크립트 HTML 엔터티"를 검색하면 해당 목적에 맞는 몇 가지 라이브러리를 찾을 수 있지만 엔터티별로 엔터티를 대체하는 위의 논리를 기반으로 구축 될 수 있습니다.


0

HTML 버튼의 값으로 HTML 엔터티 문자 (⇓)가 있어야했습니다. HTML 코드는 브라우저의 처음부터 잘 보입니다.

<input type="button" value="Embed & Share  &dArr;" id="share_button" />

이제 캐릭터를 표시 해야하는 토글을 추가했습니다. 이것은 나의 해결책이다

$("#share_button").toggle(
    function(){
        $("#share").slideDown();
        $(this).attr("value", "Embed & Share " + $("<div>").html("&uArr;").text());
    }

버튼에 ⇓가 다시 표시됩니다. 이것이 누군가를 도울 수 있기를 바랍니다.


유니 코드 이스케이프 시퀀스 (예 :)를 사용하는 것이 더 간단 "Embed & Share \u21d1"하거나 "Embed & Share ⇑"UTF-8 (또는 UTF-16 또는 ⇑ 문자를 지원하는 다른 인코딩)로 스크립트를 제공 할 수 있는 경우에 더 좋습니다 . 임의의 유니 코드 문자를 JavaScript 문자열로 굽기 위해 HTML 요소를 구문 분석하기 위해 DOM 요소를 사용하는 것은 Rube Goldberg를 자랑스럽게 만드는 교묘하고 창의적인 접근 방법이지만 좋은 습관은 아닙니다. 유니 코드 이스케이프는이 사용 사례를 처리하기 위해 특별히 언어로되어 있습니다.
Mark Amery

0

html 엔터티에 대한 사용자 지정 기능을 만들어야합니다.

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

나는 전혀 모른다, 그것은 나를 도왔다 +1 l-)
Szymon Toda

일부 엔티티 만 처리하기 때문에 투표에 실패했을 수 있습니다.
Jasen

원래 질문은 엔터티 를 디코딩 하는 방법이었습니다. 이것은 원하는 것과 반대 입니다. 그것은 인코딩 문자의 매우 제한된 엔티티. 다운 투표 툴팁에 "이 답변은 유용하지 않습니다"라고 나와 있습니다. 4 년이 지난 후에도 여전히 순 양성 점수를 받았다는 것이 놀랍습니다.
Stephen P

0

String 아래에 있다고 가정하십시오.

우리의 디럭스 캐빈은 따뜻하고 아늑한 & amp; 편안

var str = $("p").text(); // get the text from <p> tag
$('p').html(str).text();  // Now,decode html entities in your variable i.e 

str과 다시 할당

꼬리표.

그게 다야.


0

ExtJS 사용자의 경우, 라이브러리 함수의 리턴 된 값이 innerHTML 컨텐츠 인 경우와 같이 인코딩 된 문자열이 이미있는 경우 다음 ExtJS 함수를 고려하십시오.

Ext.util.Format.htmlDecode(innerHtmlContent)

이것은 5 개의 HTML 엔티티에서만 작동합니다. 문서소스 코드 에서이를 확인할 수 있습니다 .
ands

0

문자열 클래스를 확장하십시오.

String::decode = ->
  $('<textarea />').html(this).text()

방법으로 사용하십시오.

"&lt;img src='myimage.jpg'&gt;".decode()

0

이 시도 :

var htmlEntities = "&lt;script&gt;alert('hello');&lt;/script&gt;";
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을 선택했습니다.


이 코드 스 니펫이 해결책이 될 수 있지만 설명을 포함하면 게시물의 품질을 향상시키는 데 실제로 도움이됩니다. 앞으로 독자에게 질문에 대한 답변을 제공하고 있으며 해당 사람들이 코드 제안의 이유를 모를 수도 있습니다.
Johan

설명이 추가됩니다 ... 감사합니다 :)
Fawaz Al Romy

-1

여전히 한 가지 문제가 있습니다. 이스케이프 된 문자열은 입력 값에 할당 될 때 읽을 수없는 것으로 보입니다.

var string = _.escape("<img src=fake onerror=alert('boo!')>");
$('input').val(string);

예 : https://jsfiddle.net/kjpdwmqa/3/


이것은 질문에 대한 답변이 아닙니다. OP는 HTML 엔터티를 디코딩 (이스케이프 해제)하도록 요청하지만이 답변 escape에서는 Underscore.js의 방법을 사용하고 있습니다. 또한 코드 샘플이 OP의 문제를 해결하는 방법에 대한 설명이 없습니다.
ands

-1

또는 도서관도 있습니다 ..

여기 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('&copy; Ande &amp; Nonso&reg; Company Limited 2018');

건배.


he 라이브러리 에 대한 답변 이 이미 있으며 간단한 코드 예제와 왜 그리고 언제 사용해야하는지에 대한 좋은 설명이 있습니다 .
ands

-3

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;
}

사용하는 방법:

자바 스크립트 :

var txtEncoded = "&aacute; &eacute; &iacute; &oacute; &uacute;";
$('#some-id').val(html_entity_decode(txtEncoded));

HTML :

<input id="some-id" type="text" />

-3

가장 쉬운 방법은 클래스 선택기를 요소로 설정하고 다음 코드를 사용하는 것입니다.

$(function(){
    $('.classSelector').each(function(a, b){
        $(b).html($(b).text());
    });
});

더 이상 필요하지 않습니다!

나는이 문제가 있었고이 명확한 해결책을 찾았으며 잘 작동합니다.


이것은 OP의 질문에 대한 답변이 아닙니다. OP는 STRING에서 HTML 엔터티를 디코딩하도록 요청합니다. 이는 OP의 문제를 해결할뿐만 아니라 HTML 요소에서 이스케이프 된 HTML 엔터티를 수행하지 않아야 할 HTML 엔터티로 바꿉니다.
ands

-3

나는 그것이 선택한 솔루션의 정반대라고 생각합니다.

var decoded = $("<div/>").text(encodedStr).html();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.