IT박스

jQuery로 HTML 문자열 이스케이프

itboxs 2020. 10. 3. 10:13
반응형

jQuery로 HTML 문자열 이스케이프


누구든지 jQuery의 문자열에서 HTML을 이스케이프하는 쉬운 방법을 알고 있습니까? 임의의 문자열을 전달할 수 있어야하며 HTML 페이지에 표시하기 위해 적절하게 이스케이프 처리해야합니다 (JavaScript / HTML 주입 공격 방지). 이 작업을 수행하기 위해 jQuery를 확장하는 것이 가능하다고 확신하지만 현재로서는 프레임 워크에 대해 충분히 알지 못합니다.


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;

mustache.js의 솔루션 도 있습니다 .

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

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

$('<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


HTML로 이스케이프하는 경우 실제로 필요하다고 생각할 수있는 세 가지가 있습니다.

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에 대해서만 이스케이프됩니다.


나는 이것을하는 작은 함수를 썼다. 그것은 단지 탈출 ", &, <>(그러나 보통 그 모든 어쨌든 필요이다). 그것은 다음은 사용에 앞서 제안 된 솔루션을 약간 더 우아한 하나를 .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;아포스트로피 사용에 유의하십시오 (기호 엔티티 &apos;가 대신 사용되었을 수 있습니다. XML로 정의되었지만 원래 HTML 사양에 포함되지 않았으므로 모든 브라우저에서 지원되지 않을 수 있습니다. 참조 : HTML 문자 인코딩에 대한 Wikipedia 기사) ). 또한 십진수 엔터티를 사용하는 것이 16 진수를 사용하는 것보다 더 광범위하게 지원된다는 것을 어딘가에서 읽었지만 지금은 소스를 찾을 수없는 것 같습니다. (그리고 16 진수 엔터티를 지원하지 않는 브라우저는 많을 수 없습니다.)

주 : 추가 /'그들이 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]; });
    };
}());

두 버전 중 어느 것이 더 빠른지 테스트하지 않았습니다. 그렇다면 여기에 정보와 링크를 자유롭게 추가하십시오.


밑줄을 사용하기에 충분히 쉬움 :

_.escape(string) 

Underscore 는 기본 js가 제공하지 않는 많은 기능을 제공하는 유틸리티 라이브러리입니다. 밑줄과 동일한 API이지만 성능이 향상되도록 다시 작성된 lodash있습니다.


이 파티에 얼마나 늦었는지 알지만 jQuery가 필요하지 않은 매우 쉬운 솔루션이 있습니다.

escaped = new Option(unescaped).innerHTML;

편집 : 이것은 따옴표를 이스케이프하지 않습니다. 따옴표를 이스케이프해야하는 유일한 경우는 콘텐츠를 HTML 문자열 내의 속성에 인라인으로 붙여 넣는 경우입니다. 이렇게하면 좋은 디자인이 될 것이라고 상상하기 어렵습니다.

편집 2 : 성능이 중요한 경우 최고 성능 솔루션 (약 50 %)은 여전히 ​​일련의 정규식 대체입니다. 최신 브라우저는 정규식에 연산자가없고 문자열 만 포함되어 있음을 감지하고 모든 연산자를 단일 작업으로 축소합니다.


다음은 깨끗하고 명확한 JavaScript 함수입니다. "a few <many"와 같은 텍스트를 "a few & lt; many"로 이스케이프합니다.

function escapeHtmlEntities (str) {
  if (typeof jQuery !== 'undefined') {
    // Create an empty div to use as a container,
    // then put the raw text in and get the HTML
    // equivalent out.
    return jQuery('<div/>').text(str).html();
  }

  // No jQuery, so use string replace.
  return str
    .replace(/&/g, '&amp;')
    .replace(/>/g, '&gt;')
    .replace(/</g, '&lt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&apos;');
}

마지막 테스트 후 가장 빠르고 완벽하게 크로스 브라우저 와 호환되는 네이티브 자바 스크립트 (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
}

내 최종 성능 비교를보십시오 ( 스택 질문 ).


Underscore.string lib를 사용해보십시오 . jQuery와 함께 작동합니다.

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

산출:

'&lt;div&gt;Blah blah blah&lt;/div&gt;'

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()


escape()그리고 unescape(), URL에 대한 코드 / 디코드 문자열 아니며 HTML된다.

실제로 다음 스 니펫을 사용하여 프레임 워크가 필요없는 트릭을 수행합니다.

var escapedHtml = html.replace(/&/g, '&amp;')
                      .replace(/>/g, '&gt;')
                      .replace(/</g, '&lt;')
                      .replace(/"/g, '&quot;')
                      .replace(/'/g, '&apos;');

underscore.js가있는 경우 _.escape(위에 게시 된 jQuery 메서드보다 더 효율적)을 사용하십시오.

_.escape('Curly, Larry & Moe'); // returns: Curly, Larry &amp; Moe

정규식 경로를 사용하는 경우 위의 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]]);
}

이것은 좋은 안전한 예입니다 ...

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

vanilla js로 쉽게 할 수 있습니다.

문서에 텍스트 노드를 추가하기 만하면됩니다. 브라우저에 의해 이스케이프됩니다.

var escaped = document.createTextNode("<HTML TO/ESCAPE/>")
document.getElementById("[PARENT_NODE]").appendChild(escaped)

(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;"

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>


일반 JavaScript 이스케이프 예제 :

function escapeHtml(text) {
    var div = document.createElement('div');
    div.innerText = text;
    return div.innerHTML;
}

escapeHtml("<script>alert('hi!');</script>")
// "&lt;script&gt;alert('hi!');&lt;/script&gt;"

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

function htmlDecode(t){
   if (t) return $('<div />').html(t).text();
}

매력처럼 작동


이 답변 은 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.

Unfortunately, the escape() function was deprecated in JavaScript version 1.5. encodeURI() or encodeURIComponent() are alternatives, but they ignore ', so the last line of code would turn into this:

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

All major browsers still support the short code, and given the number of old websites, i doubt that will change soon.


ES6 one liner for the solution from mustache.js

const escapeHTML = str => (str+'').replace(/[&<>"'`=\/]/g, s => ({'&': '&amp;','<': '&lt;','>': '&gt;','"': '&quot;',"'": '&#39;','/': '&#x2F;','`': '&#x60;','=': '&#x3D;'})[s]);

If you are saving this information in a database, its wrong to escape HTML using a client-side script, this should be done in the server. Otherwise its easy to bypass your XSS protection.

To make my point clear, here is a exemple using one of the answers:

Lets say you are using the function escapeHtml to escape the Html from a comment in your blog and then posting it to your server.

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

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

The user could:

  • Edit the POST request parameters and replace the comment with javascript code.
  • Overwrite the escapeHtml function using the browser console.

If the user paste this snippet in the console it would bypass the XSS validation:

function escapeHtml(string){
   return string
}

All solutions are useless if you dont prevent re-escape, e.g. most solutions would keep escaping & to &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] + ";";
        }
    ) : "";
};

참고URL : https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery

반응형