Javascript에서 HtmlSpecialChars가 동일합니까?


167

분명히, 이것은 내가 생각했던 것보다 찾기가 어렵습니다. 그리고 심지어 너무 간단합니다 ...

Javascript에 내장 된 PHP의 htmlspecialchars와 동등한 기능이 있습니까? 나는 그것을 직접 구현하는 것이 상당히 쉽다는 것을 알고 있지만 가능한 경우 내장 함수를 사용하는 것이 더 좋습니다.

PHP에 익숙하지 않은 사람들을 위해, 반드시 htmlspecialchars처럼 물건을 변환 <htmltag/>&lt;htmltag/&gt;

나도 알아 escape()하고 encodeURI()이런 식으로 작동하지 않습니다.


PHP에는 정말 좋은 도구, var_dump, print_r, htmlspecialchars 등이 있습니다. 불행히도 js와 동일하지 않은 것 같습니다. js 경고가 너무 나쁩니다. 예기치 않은 (및 경고 상자에 보이지 않는) 문자열이 오는 것을 확인하는 가장 빠른 방법은 문자열 대신 문자열 길이를 경고하는 것입니다.
Melsi


stackoverflow.com/a/12034334/8804293을 참조하십시오 . 훌륭한 답변이 있습니다
Elijah Mock

답변:


330

솔루션 코드에 문제가 있습니다. 각 특수 문자의 첫 번째 항목 만 이스케이프합니다. 예를 들면 다음과 같습니다.

escapeHtml('Kip\'s <b>evil</b> "test" code\'s here');
Actual:   Kip&#039;s &lt;b&gt;evil</b> &quot;test" code's here
Expected: Kip&#039;s &lt;b&gt;evil&lt;/b&gt; &quot;test&quot; code&#039;s here

다음은 올바르게 작동하는 코드입니다.

function escapeHtml(text) {
  return text
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/"/g, "&quot;")
      .replace(/'/g, "&#039;");
}

최신 정보

다음 코드는 위와 동일한 결과를 생성하지만 특히 큰 텍스트 블록에서 성능이 우수합니다 ( jbo5112 덕분에 ).

function escapeHtml(text) {
  var map = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#039;'
  };
  
  return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}

5
이 함수의 좋은 점은 기본적으로 dom이없는 node.js에서 작동한다는 것입니다.
booyaa

6
단일 교체 및 매핑 기능을 사용하는 것이 더 빠르며 단일 교체 규모가 훨씬 좋습니다. ( jsperf.com/escape-html-special-chars/11 )
jbo5112

1
@ jbo5112 좋은 점은 교체를 위해 JS 허용 콜백을 인식하지 못했습니다. 이 코드는 이해하기가 더 쉬우 며 escapeHtml ()에서 몇 밀리 초를 면도하면 어떤 이유로 여러 번 연속 호출하지 않는 한 차이가 나지 않을 것입니다.
Kip

그러면 URL이 텍스트로 왜곡되어 Autolinker.js 와 같은 플러그인에서 사용할 수 없습니다 . 이것에 접근하는 방법이 있습니까?
Radek Matěj

4
@ RadekMatěj이 경우에도 HTML 문서에서 사용될 때 두 앰퍼샌드가 모두 인코딩되는 것이 완벽하게 유효합니다 (권장 할 것입니다). 나는 여전히 플러그인의 버그라고 생각합니다.
Kip

31

HTML 인코딩입니다. 이를 수행하는 기본 자바 스크립트 기능은 없지만 Google을 사용하여 멋지게 완성 할 수 있습니다.

예 : http://sanzon.wordpress.com/2008/05/01/neat-little-html-encoding-trick-in-javascript/

편집 :
이것은 내가 테스트 한 것입니다 :

var div = document.createElement('div');
  var text = document.createTextNode('<htmltag/>');
  div.appendChild(text);
  console.log(div.innerHTML);

산출: &lt;htmltag/&gt;


너무 나쁘면 사용자 정의 기능을 사용해야합니다.
바트 반 Heukelom

내 게시물에 포함 된 링크에서 방법을 시도 할 수 있습니다. 정말 깔끔한 컨셉.
okw

@ okw : 좋아, 먼저 당신은 이것에 링크했습니다 : yuki-onna.co.uk/html/encode.html 이것은 encodeURIComponentOP가 요구 한 것을 정확하게 하지는 않습니다. 편집 해주세요 내 -1을 취소 할 수 없습니다.
초승달 신선한

예, 해당 페이지의 코드는 논리적으로 보이지만 테스트하지는 않았습니다. 새로운 링크는 작동하지만 직접 확인했습니다. 이미 게시물을 업데이트했습니다.
okw

@BeauCielBleu : 아니요. 생성 된 유일한 노드는 단일 div요소와 텍스트 노드입니다. `<img src = bogus onerror = alert (1337)>`텍스트로 텍스트 노드를 만들면 img요소가 아닌 텍스트 노드 만 만들어 집니다.
Tim Down

26

읽을만한 가치 : http://bigdingus.com/2007/12/29/html-escaping-in-javascript/

escapeHTML: (function() {
 var MAP = {
   '&': '&amp;',
   '<': '&lt;',
   '>': '&gt;',
   '"': '&#34;',
   "'": '&#39;'
 };
  var repl = function(c) { return MAP[c]; };
  return function(s) {
    return s.replace(/[&<>'"]/g, repl);
  };
})()

참고 : 한 번만 실행하십시오. 그리고 예를 들어 이미 인코딩 된 문자열에서 실행하지 않는 &amp;된다&amp;amp;


3
이 답변은 가장 많이 채택 된 투표이어야합니다. 왜 투표가 없는지 잘 모르겠습니다. 이것은 jsperf ( jsperf.com/escape-html-special-chars/11 ) 에서 길고 (326KB Google 검색 결과) 짧은 입력 문자열 모두에서 가장 빠른 벤치마킹 입니다. 이것을 투표하십시오.
jbo5112

이 표와 가장 많은 표를 얻은 답변의 차이점은 무엇입니까? 왜 추가 내부 기능?. 설명은 사용자가 더 잘 이해하는 데 도움이 될 수 있습니다.
Kosem

19

jQuery를 사용하면 다음과 같이 될 수 있습니다.

var escapedValue = $('<div/>').text(value).html();

관련 질문 에서 jQuery로 HTML 문자열 이스케이프

주석에서 언급 했듯이이 구현에서는 큰 따옴표와 작은 따옴표가 그대로 남아 있습니다. 즉, 요소 ​​속성을 원시 HTML 문자열로 만들어야하는 경우이 솔루션을 사용해서는 안됩니다.


2
DOM에 더미 객체를 추가하여 오버 헤드가 있는지 아는 아이디어가 있습니까?
Kip

유니 코드 문자 또는 기타가있는 경우 다른 장점이 있습니까?
Kip

4
내가 찾은 것 : 큰 따옴표와 작은 따옴표는 그대로 남아 있습니다. 속성 값으로 사용하려면 문제가됩니다.
Kip

1
작은 텍스트 덩어리의 경우 모든 교체를 실행하는 데 30 배가 걸립니다. 그래도 확장 성이 뛰어납니다. Google 검색 결과 페이지 (326KB)만큼 거대한 기능을 사용하므로 Javascript를 대체하거나이 작업을 수행하는 것보다 25-30 % 더 빠릅니다. 그러나 모두 단일 교체 및 매핑 기능을 일관되게 잃습니다.
jbo5112

4
사람들이이 답변에 투표하는 방법 : answer has jquery : +1-작은 따옴표와 큰 따옴표를 피하지 않습니다 : 흠 .. (긁는 머리) .. +1. <!-- Caps rage begin --> 이 답변은 "HtmlSpecialChars equivalent"이라는 질문에 대한 답이 거의 없기 때문에 부정적인 점수를 가져야합니다. <!-- Caps rage end -->그것은 탈출하지 말고 예수 그리스도와 다른 신들을 인용한다. 세상에 당신이 jquery 사람들.
Sharky

19

HTML을 이스케이프 처리하는 기능은 다음과 같습니다.

function escapeHtml(str)
{
    var map =
    {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#039;'
    };
    return str.replace(/[&<>"']/g, function(m) {return map[m];});
}

그리고 해독 :

function decodeHtml(str)
{
    var map =
    {
        '&amp;': '&',
        '&lt;': '<',
        '&gt;': '>',
        '&quot;': '"',
        '&#039;': "'"
    };
    return str.replace(/&amp;|&lt;|&gt;|&quot;|&#039;/g, function(m) {return map[m];});
}

6

Underscore.js는이를위한 기능을 제공합니다.

_.escape(string)

&, <,>, "및 '문자를 대체하여 HTML에 삽입 할 문자열을 이스케이프합니다.

http://underscorejs.org/#escape

내장 Javascript 함수는 아니지만 이미 Underscore를 사용하고 있다면 변환 할 문자열이 너무 크지 않은 경우 자체 함수를 작성하는 것보다 더 나은 대안입니다.


5

또 다른 점은 모든 문자 매핑을 모두 버리고 대신 원치 않는 문자를 각각의 숫자 참조로 변환하는 것입니다. 예 :

function escapeHtml(raw) {
    return raw.replace(/[&<>"']/g, function onReplace(match) {
        return '&#' + match.charCodeAt(0) + ';';
    });
}

참고 지정된 정규식 만 영업 이익이 (가) HTML을 사용할 것입니다 탈출하는 상황에 따라, 탈출하고 싶어하지만 특정 문자를 처리하는, 이러한 문자가 충분하지 않을 수 있습니다. Ryan Grove의 기사 &, <,> 및 "보다 HTML 이스케이프에 대한 더 많은 내용이이 주제에 대해 잘 읽었으며, 상황에 따라 XSS 주입을 피하기 위해 다음 RegEx가 매우 필요할 수 있습니다.

var regex = /[&<>"'` !@$%()=+{}[\]]/g

3
String.prototype.escapeHTML = function() {
        return this.replace(/&/g, "&amp;")
                   .replace(/</g, "&lt;")
                   .replace(/>/g, "&gt;")
                   .replace(/"/g, "&quot;")
                   .replace(/'/g, "&#039;");
    }

샘플 :

var toto = "test<br>";
alert(toto.escapeHTML());

3

그러한 기능이 필요하지 않을 수 있습니다. 코드가 이미 브라우저 *에 있기 때문에 실제로 사용하려면 브라우저에서 뒤로 디코딩해야하는 HTML을 생성하고 인코딩하는 대신 DOM에 직접 액세스 할 수 있습니다.

innerText이스케이프 함수를 사용하는 것보다 안전하고 훨씬 빠르게 일반 텍스트를 DOM에 삽입 하려면 property를 사용하십시오 . 정적 사전 인코딩 된 문자열을에 할당하는 보다 훨씬 빠릅니다innerHTML .

사용 classList편집 클래스, dataset설정에 대한 data-속성과 setAttribute다른 사람을 위해.

이 모든 것은 당신을 위해 탈출을 처리합니다. 보다 정확하게 말하면, 이스케이프 처리가 필요하지 않으며 DOM의 텍스트 표현 인 HTML을 다루기 때문에 ** 아래에서 인코딩이 수행되지 않습니다.

// use existing element
var author = 'John "Superman" Doe <john@example.com>';
var el = document.getElementById('first');
el.dataset.author = author;
el.textContent = 'Author: '+author;

// or create a new element
var a = document.createElement('a');
a.classList.add('important');
a.href = '/search?q=term+"exact"&n=50';
a.textContent = 'Search for "exact" term';
document.body.appendChild(a);

// actual HTML code
console.log(el.outerHTML);
console.log(a.outerHTML);
.important { color: red; }
<div id="first"></div>

*이 답변은 서버 측 JavaScript 사용자 (Node.js 등)를 위한 것이 아닙니다 . )를

** 나중에 명시 적으로 실제 HTML로 변환하지 않는 한. 예를 들어 액세스 하여 다른 답변에서 제안 innerHTML을 실행할 때 발생 $('<div/>').text(value).html();합니다. 따라서 최종 목표가 문서에 일부 데이터를 삽입하는 것이라면이 방법으로 작업을 두 번 수행하게됩니다. 또한 결과 HTML에서 모든 것이 인코딩되는 것이 아니라 유효한 최소값 만 인코딩됨을 알 수 있습니다. 컨텍스트에 따라 수행 되므로이 jQuery 메소드는 따옴표를 인코딩하지 않으므로 범용 이스케이프로 사용해서는 안됩니다. 따옴표 이스케이프는 속성 값 대신 신뢰할 수 없거나 따옴표가 포함 된 데이터가 포함 된 문자열로 HTML을 구성 할 때 필요합니다. DOM API를 사용하는 경우 이스케이프 처리를 전혀 신경 쓰지 않아도됩니다.


감사합니다! 나는 그런 간단한 해결책을 오랫동안 찾았습니다. 내가 발견 한 한 가지 중요한 사실은 텍스트에 줄 바꿈이 포함되어 있으면 HTML 줄 바꿈 (예 :)으로 바꾸 el.textContent = str; el.innerHTML = el.innerHTML.replace(/\n/g, '<br>')거나 CSS white-space속성을 pre또는로 설정해야 한다는 것입니다.pre-wrap
stellatedHexahedron

@stellatedHexahedron,이 문제를 제기 해 주셔서 감사합니다. innerText대신에 추천으로 답변을 변경했습니다 textContent. 속성을 읽을 때 약간 느리고 다른 차이점 이 있지만 속성을 <br>할당 할 때 자동으로 교체 한다는 점에서 더 직관적입니다 .
사용자

2

Node.JS 사용자 (또는 브라우저에서 Jade 런타임을 사용하는 사용자)의 경우 Jade의 이스케이프 기능을 사용할 수 있습니다.

require('jade').runtime.escape(...);

다른 사람이 유지 관리하는 경우 직접 작성해도 의미가 없습니다. :)


1

나는 okw의 답변에 대해 조금 자세히 설명하고 있습니다.

이를 위해 브라우저의 DOM 기능을 사용할 수 있습니다.

var utils = {
    dummy: document.createElement('div'),
    escapeHTML: function(s) {
        this.dummy.textContent = s
        return this.dummy.innerHTML
    }
}

utils.escapeHTML('<escapeThis>&')

이 반환 &lt;escapeThis&gt;&amp;

표준 기능을 사용합니다 createElement 를 사용하여 보이지 않는 요소를 만든 다음 함수 textContent를 사용하여 문자열을 내용으로 설정 한 다음 innerHTML내용을 HTML 표현으로 가져옵니다.


0
function htmlspecialchars(str) {
 if (typeof(str) == "string") {
  str = str.replace(/&/g, "&amp;"); /* must do &amp; first */
  str = str.replace(/"/g, "&quot;");
  str = str.replace(/'/g, "&#039;");
  str = str.replace(/</g, "&lt;");
  str = str.replace(/>/g, "&gt;");
  }
 return str;
 }

0

.replace ( '&', '&'). replace ( '<', '<')를 사용하여 체인 논리가 아닌 성능과 가장 중요한 요소로 인해 레이스에서 승리하기를 바랍니다.

var mapObj = {
   '&':"&amp;",
   '<':"&lt;",
   '>':"&gt;",
   '"':"&quot;",
   '\'':"&#039;"
};
var re = new RegExp(Object.keys(mapObj).join("|"),"gi");

function escapeHtml(str) 
{   
    return str.replace(re, function(matched)
    {
        return mapObj[matched.toLowerCase()];
    });
}

console.log('<script type="text/javascript">alert('Hello World');</script>');
console.log(escapeHtml('<script type="text/javascript">alert('Hello World');</script>'));

0

반대의 경우 :

function decodeHtml(text) {
    return text
        .replace(/&amp;/g, '&')
        .replace(/&lt;/ , '<')
        .replace(/&gt;/, '>')
        .replace(/&quot;/g,'"')
        .replace(/&#039;/g,"'");
}

문제는 엔터티를 디코딩하는 방법을 묻지 않습니다. 이것은 질문이 요구하는 것과 반대입니다.
Quentin

이 단지 대체 할 첫 번째 인스턴스 &lt;&gr;문자열을.
Quentin

이 만 5 자 (유니 코드를 지원하지 않는 문서의 외부) 디코드 할 수 있어야합니다 이스케이프를, 그것은 사람 디코딩하지 않을 수 있습니다 이스케이프를.
Quentin

세미콜론이 선택적 일 때의 규칙은 고려하지 않습니다.
Quentin

HTML이 다음 To write a greater than sign in HTML type &amp;gt;과 같이 표시되면>&gt;
Quentin

0

OWASP 는 "[e] x 영숫자 문자를 제외하고 ASCII 값이 256보다 작은 모든 문자를&#xHH; 제외하고 [an] 속성에서 전환되지 않도록 형식 (또는 가능한 경우 명명 된 엔티티)을 사용하여 합니다."

다음은 사용법 예제와 함께이를 수행하는 함수입니다.

function escapeHTML(unsafe) {
  return unsafe.replace(
    /[\u0000-\u002F]|[\u003A-\u0040]|[\u005B-\u00FF]/g,
    c => '&#' + ('000' + c.charCodeAt(0)).substr(-4, 4) + ';'
  )
}
document.querySelector('div').innerHTML =
  '<span class=' +
  escapeHTML('this should break it! " | / % * + , - / ; < = > ^') +
  '>' +
  escapeHTML('<script>alert("inspect the attributes")\u003C/script>') +
  '</span>'
<div></div>


-1
function htmlEscape(str){
    return str.replace(/[&<>'"]/g,x=>'&#'+x.charCodeAt(0)+';')
}

이 솔루션은 문자의 숫자 코드를 사용합니다 (예 <:&#60; .

map을 사용하는 솔루션 보다 성능이 약간 떨어지지 만 다음 과 같은 장점이 있습니다.

  • 라이브러리 또는 DOM에 의존하지 않음
  • 기억하기 매우 쉽습니다 (5 개의 HTML 이스케이프 문자를 외울 필요는 없습니다)
  • 작은 코드
  • 상당히 빠름 (여전히 5 체인 교체보다 빠름)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.