Bài viết này trình bày lý do đằng sau việc sử dụng thuộc tính dangerouslySetInnerHTML
trong ứng dụng React, tương đương với thuộc tính innerHTML
trong trình duyệt DOM
dangerouslySetInnerHTML
là gì?
dangerouslySetInnerHTML
là một thuộc tính mà bạn có thể sử dụng trên các phần tử HTML trong ứng dụng React để thiết lập nội dung của chúng theo chương trình. Thay vì sử dụng bộ chọn để lấy phần tử HTML, sau đó đặt innerHTML
của nó, bạn có thể sử dụng thuộc tính này trực tiếp trên phần tử
Khi dangerouslySetInnerHTML
được sử dụng, React cũng biết rằng nội dung của phần tử cụ thể đó là động và đối với nút con của nút đó, nó chỉ cần bỏ qua phần so sánh với DOM ảo để đạt được hiệu suất cao hơn
Như tên của thuộc tính gợi ý, nó có thể nguy hiểm khi sử dụng vì nó làm cho mã của bạn dễ bị tấn công bằng kịch bản chéo trang [XSS]. Điều này trở thành một vấn đề đặc biệt nếu bạn đang tìm nạp dữ liệu từ nguồn của bên thứ ba hoặc hiển thị nội dung do người dùng gửi
Khi nào thì sử dụng dangerouslySetInnerHTML
Trường hợp sử dụng mà bạn cần đặt nội dung HTML của phần tử DOM là khi bạn điền phần tử
const App = [] => { const data = 'lorem ipsum'; return []; } export default App; 4 với dữ liệu đến từ trình soạn thảo văn bản đa dạng thức. Hãy tưởng tượng bạn có một trang web nơi mọi người có thể gửi nhận xét và bạn cho phép họ sử dụng trình soạn thảo văn bản đa dạng thức. Trong trường hợp này, đầu ra của trình soạn thảo văn bản đa dạng thức đó có thể là HTML với các thẻ nhưconst App = [] => { const data = 'lorem ipsum'; return []; } export default App; 5,const App = [] => { const data = 'lorem ipsum'; return []; } export default App; 6 vàconst App = [] => { const data = 'lorem ipsum'; return []; } export default App; 7Consider the following code snippet, which would render the string without being aware of the
const App = [] => { const data = 'lorem ipsum'; return []; } export default App; 6 tag in it — meaning that the output would be just the string itself without any bold text, like so: lorem ipsum. const App = [] => { const data = 'lorem ipsum'; return [{data}]; } export default App;Nhưng khi sử dụng
dangerouslySetInnerHTML
, React sẽ nhận biết được các thẻ HTML và hiển thị chúng đúng cách. Lần này, đầu ra sẽ được hiển thị chính xác với văn bản in đậm [i. e. , lorem ipsum]const App = [] => { const data = 'lorem ipsum'; return []; } export default App;Lưu ý rằng nó phải là một đối tượng có khóa
const App = [] => { const data = `lorem ipsum`; return []; } export default App; const App = [] => { const data = `lorem ipsum `; return []; } export default App; 0 được chuyển đếndangerouslySetInnerHTML
. Ngoài ra, phần tử bạn sử dụng thuộc tínhdangerouslySetInnerHTML
không được có bất kỳ phần tử con nào, do đó việc sử dụng phần tửconst App = [] => { const data = 'lorem ipsum'; return []; } export default App; 4 làm thẻ tự đóngYêu cầu chuyển một đối tượng chỉ là một biện pháp bảo vệ khác để ngăn các nhà phát triển sử dụng nó mà không xem qua tài liệu và nhận thức được mối nguy hiểm tiềm tàng
Vệ sinh khi sử dụng
dangerouslySetInnerHTML
Các ví dụ trên không gây nguy hiểm khi kết xuất. Tuy nhiên, có thể có một số trường hợp phần tử HTML thực thi tập lệnh
Xem xét các ví dụ sau trong đó sự kiện JavaScript được đính kèm với phần tử HTML. Mặc dù đây là những ví dụ vô hại nhưng chúng là bằng chứng về các khái niệm cho thấy cách một phần tử HTML có thể bị khai thác để chạy các tập lệnh độc hại
Hơn 200 nghìn nhà phát triển sử dụng LogRocket để tạo ra trải nghiệm kỹ thuật số tốt hơn
Tìm hiểu thêm →const App = [] => { const data = `lorem ipsum`; return []; } export default App; const App = [] => { const data = `lorem ipsum `; return []; } export default App;May mắn thay, có các công cụ làm sạch cho HTML, giúp phát hiện các phần độc hại tiềm tàng trong mã HTML và sau đó xuất ra một phiên bản sạch và an toàn của nó. Trình khử trùng phổ biến nhất cho HTML là DOMPurify
Hãy sử dụng bản trình diễn trực tuyến của nó để làm sạch các mã HTML đã đề cập ở trên và xem cách nó phát hiện và lọc ra các phần mã có khả năng gây nguy hiểm khi thực thi
Original lorem ipsum Sanitized lorem ipsumOriginal lorem ipsum Sanitized lorem ipsumĐó là một phương pháp hay để sử dụng chất khử trùng ngay cả khi chúng ta tin tưởng vào nguồn dữ liệu. Với gói DOMPurify được sử dụng, một trong những ví dụ trên sẽ như sau
import DOMPurify from 'dompurify' const App = [] => { const data = `lorem ipsum` const sanitizedData = [] => [{ __html: DOMPurify.sanitize[data] }] return []; } export default App;Hàm
const App = [] => { const data = `lorem ipsum`; return []; } export default App; const App = [] => { const data = `lorem ipsum `; return []; } export default App; 5 trả về một đối tượng có khóaconst App = [] => { const data = `lorem ipsum`; return []; } export default App; const App = [] => { const data = `lorem ipsum `; return []; } export default App; 0, có giá trị được trả về từ hàmconst App = [] => { const data = `lorem ipsum`; return []; } export default App; const App = [] => { const data = `lorem ipsum `; return []; } export default App; 7Như mong đợi, khi chúng tôi di chuột qua văn bản in đậm, không có chức năng cảnh báo nào được thực hiện
Lưu ý rằng vì DOMPurify cần một cây DOM và môi trường Node không có, nên bạn phải sử dụng gói
const App = [] => { const data = `lorem ipsum`; return []; } export default App; const App = [] => { const data = `lorem ipsum `; return []; } export default App; 8 để tạo một đối tượngconst App = [] => { const data = `lorem ipsum`; return []; } export default App; const App = [] => { const data = `lorem ipsum `; return []; } export default App; 9 và khởi tạoOriginal lorem ipsum Sanitized lorem ipsum0 với nó hoặc chỉ sử dụng góiOriginal lorem ipsum Sanitized lorem ipsum1, gói gọn cả hai đối tượngOriginal lorem ipsum Sanitized lorem ipsum0 vàNếu bạn thích tùy chọn đầu tiên, bạn có thể tham khảo đoạn mã sau từ tài liệu của
Original lorem ipsum Sanitized lorem ipsum0const createDOMPurify = require['dompurify']; const { JSDOM } = require['jsdom']; const window = new JSDOM[''].window; const DOMPurify = createDOMPurify[window]; const clean = DOMPurify.sanitize[dirty];Phần kết luận
Tóm lại,
dangerouslySetInnerHTML
không gì khác ngoài sự thay thế củainnerHTML
trong React và nên được sử dụng cẩn thận. Mặc dù cái tên cho thấy sự nguy hiểm khi sử dụng, nhưng thực hiện biện pháp cần thiết bằng cách sử dụng trình khử trùng được phát triển tốt để đảm bảo mã sạch và không chạy các tập lệnh không mong muốn khi được hiển thị trong nút ReactChủ Đề