Thoát chuỗi HTML bằng jQuery


609

Có ai biết một cách dễ dàng để thoát HTML khỏi các chuỗi trong jQuery không? Tôi cần có khả năng vượt qua một chuỗi tùy ý và thoát nó đúng cách để hiển thị trong trang HTML (ngăn chặn các cuộc tấn công tiêm JavaScript / HTML). Tôi chắc chắn có thể mở rộng jQuery để làm điều này, nhưng tôi không biết đủ về khung công tác tại thời điểm này để thực hiện điều này.


Xem thêm perf: jsperf.com/ Hãy
Roussy

Câu trả lời:


445

Vì bạn đang sử dụng jQuery , bạn chỉ có thể đặt thuộc tính của thành phần 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;

57
Bạn đã bỏ lỡ điểm mà bạn phải truy cập $ ("div.someClass"). Html () để đưa phiên bản thoát ra ngoài.
Morten Christiansen

16
Đây không phải là trình duyệt chéo an toàn nếu chuỗi của bạn có khoảng trắng và \ n \ r \ t ký tự trong đó
nivcaner

20
@travis Điều này được ghi lại trên trang web jQuery: "Do các biến thể của trình phân tích cú pháp HTML trong các trình duyệt khác nhau, văn bản được trả về có thể khác nhau ở dòng mới và khoảng trắng khác." api.jquery.com/text
geofflee

3
@mkuity nếu bạn đã sử dụng giải pháp này, bạn sẽ không gặp vấn đề gì với việc làm đó như: $(element2).attr("some-attr", $(element1).html());Xem ví dụ này: jsbin.com/atibig/1/edit
travis

16
Điều này KHÔNG thoát khỏi dấu ngoặc kép và dấu ngoặc kép là xấu! wonko.com/post/html-escaping
Lior

601

Ngoài ra còn có giải pháp từ 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];
  });
}

7
Lưu ý rằng, thật tò mò, 'được ánh xạ tới một thực thể có định dạng thập phân , trong khi /sử dụng định dạng hex .
mkuity0

43
Đây phải là câu trả lời được chấp nhận - nó đơn giản, hiệu quả, không yêu cầu phụ thuộc và thực hiện chính xác những gì được dự định mà không có hack nào tối nghĩa.
lorefnon

6
hướng dẫn chuyển đổi \nthành <br>gì?
amwinter

2
Đây là một liên kết được cập nhật tới nguồn: github.com/janl/mustache.js/blob/
Kẻ

8
@amwinter, tôi đã mở rộng tập lệnh ở trên thêm "\ n": '<br>' vào bản đồ thực thể và cập nhật regrec thành / [& <> "'\ /] | [\ n] / g
walv

182
$('<div/>').text('This is fun & stuff').html(); // "This is fun &amp; stuff"

Nguồn: http://debuggable.com/posts/encode-html-entities-with-jquery:480f4dd6-13cc-4ce9-8071-4710cbdd56cb


11
Như đã đề cập trong câu trả lời trên, giải pháp này không được đảm bảo để duy trì khoảng trắng.
geofflee

47
Cần lưu ý rằng điều này không có gì để thoát khỏi dấu ngoặc đơn hoặc kép. nếu bạn định đặt giá trị vào thuộc tính HTML, đây có thể là một vấn đề.
Kip

6
@Kip: @travis nhận thấy rằng attr()phương thức của jQuery (ít nhất là 1.8.3) thực hiện mã hóa riêng, để các chuỗi không được mã hóa có thể được truyền trực tiếp ; ví dụ:$('<div/>').attr('test-attr', '\'Tis "fun" & stuff')[0].outerHTML
mkuity0

1
@tarekahf Thật kỳ lạ. Phiên bản jQuery nào bạn đang sử dụng? Mã ví dụ có hoạt động không nếu bạn sao chép-dán nguyên văn? Hoạt động tốt với jQuery mới nhất (3.1.0) tại đây: jsbin.com/fazimigayo/1/edit?html,js,console,output (và nó cũng sẽ hoạt động trên tất cả các phiên bản trước đó)
Henrik N

1
@tarekahf $('<div/>')tạo một divphần tử mới không được đính kèm với DOM. Vì vậy, nó sẽ không thay đổi bất kỳ yếu tố hiện có. Có một chút khó hiểu khi jQuery sử dụng cùng một $()chức năng để tìm các phần tử ( $('div')) và để tạo ra chúng, và để biết thêm một số thứ khác ngoài việc :)
Henrik N

61

Nếu bạn đang thoát khỏi HTML, chỉ có ba điều mà tôi có thể nghĩ rằng điều đó thực sự cần thiết:

html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");

Tùy thuộc vào trường hợp sử dụng của bạn, bạn cũng có thể cần phải làm những việc như "để &quot;. Nếu danh sách đủ lớn, tôi chỉ cần sử dụng một mảng:

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() sẽ chỉ thoát nó cho URL, không phải cho HTML.


13
Biểu thức chính quy này sẽ tạo ra kết quả lạ nếu HTML được đề cập đã thoát các thực thể. Ví dụ: thoát khỏi "Tom & amp; Jerry" sẽ tạo ra "Tom & amp; amp; Jerry"
Ryan

12
Vui lòng sử dụng varđể khai báo itemtại địa phương; Dù sao, đừng sử dụng một for … invòng lặp khi lặp qua một mảng! Sử dụng một forvòng lặp thông thường thay thế. Ồ, và nó encodeURIComponent, không phải escapeURIComponent.
Marcel Korpel

3
Nếu bạn đang làm việc với các thuộc tính thẻ, thì bạn cũng sẽ cần thoát dấu ngoặc kép và / hoặc dấu ngoặc kép. Tài liệu PHP cho htmlspecialchars chứa một danh sách hữu ích các chuyển đổi mà nó thực hiện. php.net/htmlspecialchars
geofflee

4
Chỉ là một lời nhắc nhở tử tế cho những người mới, đừng sử dụng điều này nếu bạn dự định có các ký tự không phải tiếng Anh ở đâu đó trên trang web của mình ... Rõ ràng điều này sẽ không xảy ra vì các ký tự có dấu như 'é' : &eacute; Đây là danh sách các thực thể html, để tham khảo: w3schools.com/tags/ref_entities.asp
LoganWolfer

11
@Ryan: Mặc dù đáng để chỉ ra rằng giải pháp này không xử lý chính xác các chuỗi đã được mã hóa, nhưng nó cũng không có giá trị gì áp dụng tương tự cho hầu hết - có thể là tất cả - các giải pháp trên trang này.
mkuity0

37

Đủ dễ dàng để sử dụng gạch dưới:

_.escape(string) 

Underscore là một thư viện tiện ích cung cấp rất nhiều tính năng mà js bản địa không cung cấp. Ngoài ra còn có lodash là API giống như gạch dưới nhưng được viết lại để có hiệu suất cao hơn.


36

Tôi đã viết một chức năng nhỏ bé mà làm điều này. Nó chỉ thoát ", &, <>(nhưng thường đó là tất cả bạn cần anyway). Nó thanh lịch hơn một chút sau đó các giải pháp được đề xuất trước đó ở chỗ nó chỉ sử dụng một .replace() để thực hiện tất cả các chuyển đổi. ( EDIT 2: Giảm độ phức tạp của mã làm cho hàm nhỏ hơn và gọn gàng hơn, nếu bạn tò mò về mã gốc, hãy xem phần cuối của câu trả lời này.)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&<>]/g, function (a) {
        return { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' }[a];
    });
}

Đây là Javascript đơn giản, không sử dụng jQuery.

Chạy trốn /'quá

Chỉnh sửa để đáp lại bình luận của mkuity .

Các chức năng trên có thể dễ dàng được mở rộng để bao gồm bất kỳ nhân vật. Để chỉ định thêm ký tự để thoát, chỉ cần chèn cả hai trong lớp ký tự trong biểu thức chính quy (tức là bên trong /[...]/g) và dưới dạng một mục trong chrđối tượng. ( EDIT 2: Rút ngắn chức năng này theo cách tương tự.)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&'\/<>]/g, function (a) {
        return {
            '"': '&quot;', '&': '&amp;', "'": '&#39;',
            '/': '&#47;',  '<': '&lt;',  '>': '&gt;'
        }[a];
    });
}

Lưu ý cách sử dụng &#39;dấu nháy đơn ở trên (thực thể tượng trưng &apos;có thể đã được sử dụng thay thế - nó được định nghĩa bằng XML, nhưng ban đầu không được bao gồm trong đặc tả HTML và do đó có thể không được hỗ trợ bởi tất cả các trình duyệt. Xem: Bài viết Wikipedia về mã hóa ký tự HTML. ). Tôi cũng nhớ lại việc đọc ở đâu đó rằng sử dụng các thực thể thập phân được hỗ trợ rộng rãi hơn so với sử dụng thập lục phân, nhưng dường như tôi không thể tìm thấy nguồn cho điều đó ngay bây giờ. (Và không thể có nhiều trình duyệt ngoài đó không hỗ trợ các thực thể thập lục phân.)

Lưu ý: Việc thêm /'vào danh sách các ký tự thoát không hoàn toàn hữu ích, vì chúng không có bất kỳ ý nghĩa đặc biệt nào trong HTML và không cần phải thoát.

escapeHtmlChức năng gốc

EDIT 2: Hàm ban đầu đã sử dụng một biến ( chr) để lưu trữ đối tượng cần thiết cho cuộc .replace()gọi lại. Biến này cũng cần một hàm ẩn danh bổ sung để phạm vi nó, làm cho hàm (không cần thiết) lớn hơn một chút và phức tạp hơn.

var escapeHtml = (function () {
    'use strict';
    var chr = { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' };
    return function (text) {
        return text.replace(/[\"&<>]/g, function (a) { return chr[a]; });
    };
}());

Tôi chưa thử nghiệm phiên bản nào trong hai phiên bản nhanh hơn. Nếu bạn làm như vậy, hãy thêm thông tin và liên kết về nó ở đây.


Cảm ơn bạn đã dành thời gian, @Zrajm. Điểm tốt về không cần thoát; Bất cứ ý tưởng tại sao cả hai mustache.jsunderscore.jslàm điều đó? Nói về cái sau: nó chỉ nhận ra các thực thể số (đại diện '/'), ở dạng hex chữ hoa khi không thoát. Do đó, văn bản thoát ra mustache.js- trong đó tò mò sử dụng hỗn hợp hex. và định dạng thập phân - sẽ không được bỏ qua một cách chính xác underscore.js. Tôi tự hỏi làm thế nào các thư viện phổ biến khác đối phó với điều đó.
mkuity0

1
Biểu mẫu hex chữ thường là hình thức được hỗ trợ nhiều nhất, vì vậy đó có thể là hình thức mà các thư viện nên chuyển đổi thành . (Tất nhiên cả hai biểu mẫu sẽ hoạt động khi chuyển đổi từ .) - Dấu nháy đơn 'có một số loại chức năng dành riêng trong XML (và do đó, XHTML, tôi tưởng tượng?), Đó là lý do tại sao XML (nhưng không phải HTML) có thực thể được đặt tên &apos;. Chính xác thì tại sao hay theo cách nào thì đó là một khu bảo tồn mà tôi không biết. - Dấu gạch chéo là đặc biệt trong các URL, nhưng điều đó không thực sự đảm bảo chúng được đưa vào để thoát HTML (vì mã hóa URL là một thứ hoàn toàn khác).
zrajm

Re &apos;: đúng: chỉ sử dụng an toàn trong XHTML ; trực tiếp từ miệng của nguồn đám đông - tôi nhấn mạnh: "(...) được đọc bởi bộ xử lý HTML tuân thủ , (...) sử dụng & apos; hoặc tham chiếu thực thể tùy chỉnh có thể không được hỗ trợ (...)" - trong thực tế : các trình duyệt hiện đại hỗ trợ nó ngay cả trong HTML . Trường hợp lại trong số hex. (cùng một nguồn; nhấn mạnh của tôi): "Chữ x phải là chữ thường trong tài liệu XML. [Khác] hhhh có thể trộn chữ hoa và chữ thường, mặc dù chữ hoa là kiểu thông thường ." Để chúng tôi tự hỏi ai đã quyết định mã hóa dấu gạch chéo; có lẽ thực sự chỉ là một sự nhầm lẫn giữa mã hóa URI và HTML?
mkuity0

2
Suy nghĩ cuối cùng: có vẻ như /không cần mã hóa, nhưng mã hóa 'vẫn có vẻ hữu ích để xử lý một cách an toàn trường hợp trường hợp trong đó một chuỗi được mã hóa được sử dụng làm giá trị thuộc tính được đặt trong các dấu ngoặc đơn .
mkuity0

Cả hai đều chậm. Giải pháp nhanh nhất bằng lề hai chữ số là một loạt các thay thế được truyền qua các chuỗi thay vì các hàm.
Adam Leggett

34

Tôi nhận ra rằng tôi đến bữa tiệc này muộn thế nào, nhưng tôi có một giải pháp rất dễ dàng mà không cần jQuery.

escaped = new Option(unescaped).innerHTML;

Chỉnh sửa: Điều này không thoát khỏi dấu ngoặc kép. Trường hợp duy nhất mà dấu ngoặc kép cần được thoát là nếu nội dung sẽ được dán nội tuyến vào một thuộc tính trong chuỗi HTML. Thật khó cho tôi để tưởng tượng một trường hợp làm điều này sẽ được thiết kế tốt.

Chỉnh sửa 3: Để có giải pháp nhanh nhất, hãy kiểm tra câu trả lời ở trên từ Saram. Cái này là ngắn nhất


Điều này không thay đổi dấu ngoặc kép - ít nhất là ngay bây giờ trong Firefox 52.
getetbro

1
Thoát báo giá chỉ có chức năng liên quan trong các thuộc tính. Vì chúng tôi đang thoát <>, cũng không có lợi ích gì khi thoát các trích dẫn, trừ khi mục đích của nội dung được tạo là đi vào một thuộc tính.
Adam Leggett

31

Đây là một hàm JavaScript rõ ràng. Nó sẽ thoát văn bản như "một vài <nhiều" thành "một vài & lt; nhiều".

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

28

Sau các thử nghiệm cuối cùng, tôi có thể đề xuất giải pháp javaScript (DOM) tương thích trình duyệt nhanh nhất và hoàn toàn chéo :

function HTMLescape(html){
    return document.createElement('div')
        .appendChild(document.createTextNode(html))
        .parentNode
        .innerHTML
}

Nếu bạn lặp lại nhiều lần, bạn có thể làm điều đó với các biến đã được chuẩn bị một lần:

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

Nhìn vào so sánh hiệu suất cuối cùng của tôi ( câu hỏi ngăn xếp ).


2
Có cần thiết phải sử dụng hai nút? Làm thế nào về chỉ một:var p = document.createElement('p'); p.textContent = html; return p.innerHTML;
Dan Dascalescu

2
@DanDascalescu: Theo MDN , textContentchức năng này chỉ được Chrome 1+, Firefox 2, IE9, Opera 9.64 và Safari 3 hỗ trợ (hai phần sau được chú thích "có thể sớm hơn"). Do đó, nó sẽ phá vỡ yêu cầu "hoàn toàn tương thích trình duyệt" của OP.
zb226

p.innerText = html; return p.innerHTML
Bekim Bacaj

24

Hãy thử lib Underscore.opes , nó hoạt động với jQuery.

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

đầu ra:

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

20
Thư viện gạch dưới chính bây giờ có _.escape()chức năng tiện ích.
codeape

15

Tôi đã nâng cao ví dụ mustache.js thêm escapeHTML()phương thức vào đối tượng chuỗi.

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

String.prototype.escapeHTML = function() {
    return String(this).replace(/[&<>"'\/]/g, function (s) {
        return __entityMap[s];
    });
}

Cách đó khá dễ sử dụng. "Some <text>, more Text&Text".escapeHTML()


Hữu ích, nhưng tôi cũng chuyển __entityMapvào chức năng phạm vi địa phương. Và gói tất cả những thứ này vàoif (typeof String.prototype.escapeHTML !== 'function'){...}
FlameStorm

15

escape()unescape()được dự định để mã hóa / giải mã chuỗi cho URL, không phải HTML.

Trên thực tế, tôi sử dụng đoạn mã sau để thực hiện thủ thuật không yêu cầu bất kỳ khuôn khổ nào:

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

Nếu bạn sắp có "s thì bạn cần thêm ít nhất 'và `` vào cuộc cạnh tranh. Chúng chỉ thực sự cần thiết cho dữ liệu thẻ chuỗi bên trong các phần tử trong html. Đối với chính dữ liệu html (thẻ bên ngoài), chỉ cần 3 cái đầu tiên.
Marius

10

Nếu bạn có underscore.js, hãy sử dụng _.escape(hiệu quả hơn phương thức jQuery được đăng ở trên):

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

5

Nếu bạn đang đi theo lộ trình regex, có một lỗi trong ví dụ của tghw ở trên.

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

2
Tôi tin rằng nó nên dành cho (var item in findReplace) {escoped = escoped.replace (findReplace [item] [0], findReplace [item] [1]); }
Chris Stephens

5

Đây là một ví dụ an toàn tốt đẹp ...

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

4
Những loại ngoại lệ nào bạn đang đàn áp ở đó?
Stefan Majewsky

3

Bạn có thể dễ dàng làm điều đó với vanilla js.

Đơn giản chỉ cần thêm một nút văn bản tài liệu. Nó sẽ được thoát khỏi trình duyệt.

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

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

Không có biến toàn cục, một số tối ưu hóa bộ nhớ. Sử dụng:

"some<tag>and&symbol©".htmlEscape({'©': '&copy;'})

kết quả là:

"some&lt;tag&gt;and&amp;symbol&copy;"

2

2 phương pháp đơn giản không yêu cầu ...

Bạn có thể mã hóa tất cả các ký tự trong chuỗi của mình như thế này:

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

Hoặc chỉ cần nhắm mục tiêu các nhân vật chính phải lo lắng về &, ngắt dòng, <, >, "'như:

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>


2

Ví dụ thoát JavaScript đơn giản:

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

3
Các câu trả lời chỉ có mã không được khuyến khích vì chúng không giải thích cách chúng giải quyết vấn đề. Vui lòng cập nhật câu trả lời của bạn để giải thích cách cải thiện này đối với các câu trả lời được chấp nhận và nâng cao khác mà câu hỏi này đã có. Ngoài ra, câu hỏi này đã 9 tuổi, những nỗ lực của bạn sẽ được đánh giá cao hơn bởi những người dùng có câu hỏi chưa được trả lời gần đây. Vui lòng xem lại Làm thế nào để tôi viết một câu trả lời tốt .
FluffyKitten

1
@FluffyKitten ở đây là một bài đăng blog cực kỳ độc đáo về những ưu điểm và nhược điểm của chức năng đó giải thích chi tiết mọi thứ bạn muốn biết :) shebang.brandonmi INTERN.com/
db306

@ db306 Câu trả lời được gắn cờ là chất lượng thấp vì câu trả lời chỉ có mã không đáp ứng các nguyên tắc Stack Overflow - xem Cách viết câu trả lời hay . Nhận xét của tôi đã được thêm vào trong quá trình xem xét để giải thích những gì cần thiết để cải thiện nó, tức là câu trả lời cần được cập nhật để giải thích những gì mã làm và cách cải thiện các câu trả lời hiện có. Các upvote là từ các nhà phê bình khác để chứng thực điều này. Thêm một liên kết bên ngoài vào các bình luận vẫn không đáp ứng các nguyên tắc SO. Thay vào đó Andrew cần bao gồm các thông tin liên quan trực tiếp trong câu trả lời của mình.
FluffyKitten

Lưu ý rằng thương hiệu DOT com đã hết hạn và hiện đang đỗ. Địa chỉ shebang mới là shebang.mi INTERN.net/foolproof-html-escaping-in-javascript/.
Brandon

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

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

hoạt động như một lá bùa


văn bản sẽ xóa các thẻ html, nhưng $ ('<div />'). html (t) .html (); hoạt động
Bass Jobsen

0

Câu trả lời này cung cấp các phương thức jQuery và JS bình thường, nhưng đây là cách ngắn nhất mà không cần sử dụng DOM:

unescape(escape("It's > 20% less complicated this way."))

Chuỗi thoát: It%27s%20%3E%2020%25%20less%20complicated%20this%20way.

Nếu không gian thoát làm phiền bạn, hãy thử:

unescape(escape("It's > 20% less complicated this way.").replace(/%20/g, " "))

Chuỗi thoát: It%27s %3E 20%25 less complicated this way.

Thật không may, escape()chức năng này không được dùng trong phiên bản JavaScript 1.5 . encodeURI()hoặc encodeURIComponent()là các lựa chọn thay thế, nhưng chúng bỏ qua ', vì vậy dòng mã cuối cùng sẽ biến thành thế này:

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

Tất cả các trình duyệt chính vẫn hỗ trợ mã ngắn và với số lượng trang web cũ, tôi nghi ngờ điều đó sẽ sớm thay đổi.


Đây là mã hóa URL. Câu hỏi là về việc thoát HTML, rất khác nhau.
thelem

@thelem, không phải nếu các chuỗi được nhúng trong mảng JavaScript được nhúng trong HTML, nhưng tôi đồng ý rằng đó là về việc thoát HTML đơn giản để nó có thể được hiển thị ngay lập tức dưới dạng văn bản.
Cees Timmerman

0

ES6 một lớp lót cho giải pháp từ mustache.js

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

-2

Nếu bạn đang lưu thông tin này trong cơ sở dữ liệu , việc thoát HTML bằng cách sử dụng tập lệnh phía máy khách là sai , điều này nên được thực hiện trong máy chủ . Nếu không, nó dễ dàng bỏ qua bảo vệ XSS của bạn.

Để làm rõ quan điểm của tôi, đây là một ví dụ sử dụng một trong những câu trả lời:

Hãy nói rằng bạn đang sử dụng hàm escHtml để thoát Html khỏi một bình luận trong blog của bạn và sau đó đăng nó lên máy chủ của bạn.

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

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

Người dùng có thể:

  • Chỉnh sửa các tham số yêu cầu POST và thay thế nhận xét bằng mã javascript.
  • Ghi đè chức năng escHtml bằng bảng điều khiển trình duyệt.

Nếu người dùng dán đoạn mã này vào bảng điều khiển, nó sẽ bỏ qua xác thực XSS:

function escapeHtml(string){
   return string
}

Tôi không đồng ý. Để bỏ qua sự bảo vệ XSS này, bạn phải sử dụng một cuộc tấn công XSS (tiêm một đoạn script vô hiệu hóa việc thoát), đây là điều bạn thực sự đang chặn. Trong một số trường hợp, thực sự thích hợp hơn để thoát trên máy khách, ví dụ: nếu dữ liệu đến từ API REST phải trả về JSON chuẩn.
ItalyPaleAle 13/03/2015

@Qualcuno Nếu bạn đang thực hiện xác nhận này trong máy khách và đăng thông tin này lên máy chủ tin tưởng thì nó đã được xác thực, người dùng có thể chỉ cần chỉnh sửa yêu cầu và tập lệnh sẽ được lưu trong cơ sở dữ liệu.
Kauê Gimenes

@Qualcuno Tôi bao gồm một số ví dụ để làm rõ quan điểm của tôi.
Kauê Gimenes

1
Câu hỏi là về việc thoát các chuỗi nhận được từ máy chủ để hiển thị chúng trên trình duyệt. Những gì bạn đang nói là về việc thoát các chuỗi trước khi gửi chúng đến máy chủ, đó là một điều khác (mặc dù bạn đúng, ở đó và nó quay trở lại quy tắc cũ không bao giờ chấp nhận một cách mù quáng bất kỳ đầu vào nào từ máy khách )
ItalyPaleAle

@Qualcuno Đây là một câu hỏi phổ biến trong Stackoverflow và tôi tin rằng đây là một điểm quan trọng cần được đề cập. Đó là lý do tại sao tôi trả lời.
Kauê Gimenes

-2

Tất cả các giải pháp đều vô dụng nếu bạn không ngăn chặn tái thoát, ví dụ như hầu hết các giải pháp sẽ tiếp tục thoát &đến &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] + ";";
        }
    ) : "";
};

4
Điều đó được gọi là thoát kép và cần được khắc phục bằng cách đảm bảo dữ liệu đầu vào của bạn chưa được thoát. Điều gì xảy ra nếu bạn muốn hiển thị theo nghĩa đen & lt; cho người dùng? Hoặc có lẽ văn bản sẽ được sử dụng lại ở nơi khác, và phụ thuộc vào việc trốn thoát đã xảy ra?
từ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.