React,TypeScript 사용중인 프로젝트에서 에디터를 통해 내려받은 코드를 본문에 노출되도록 하고 싶었다.
dangerouslysetinnerhtml 을 그대로 아래와 같이 사용하여 표시를 할 수 있다.
<div dangerouslySetInnerHTML={{ __html: content }}>
</div>
하지만 이대로 사용시에는 악성 스크립트가 작동될 수 있는 위험성이 있다.
XSS 공격?
크로스 사이트 스크립팅 또는 교차 사이트 스크립팅(Cross Site Scripting, XSS)은 공격자가 상대방의 브라우저에 스크립트가 실행되도록 해 사용자의 세션을 가로채거나, 웹사이트를 변조하거나, 악의적 콘텐츠를 삽입하거나, 피싱 공격을 진행하는 것을 말합니다. XSS 공격은 스크립트 언어와 취약한 코드를 공격 대상으로 합니다.
출처:https://nordvpn.com/ko/blog/xss-attack/
따라서 안전한 버전으로 출력해주는 dompurify 라이브러리를 사용하고자 한다.
[ dompurify 사용법 ]
설치
npm i dompurify
npm i @types/dompurify
사용
import DOMPurify from 'dompurify'; //1.import
const dummyContent = `<h2>내용입니다.</h2><h1><span style="background-color: rgb(255, 255, 255); color: rgb(0, 0, 0); ">What is </span><span style="background - color: rgb(255, 255, 255); color: rgb(230, 0, 0); ">Lorem</span><span style="background - color: rgb(255, 153, 0); color: rgb(0, 0, 0); "> Ipsum</span><span style="background - color: rgb(255, 255, 255); color: rgb(0, 0, 0); ">?</span></h1><p><strong style="background - color: rgb(255, 255, 255); color: rgb(0, 0, 0); "><u>Lorem Ipsum</u></strong><span style="background - color: rgb(255, 255, 255); color: rgb(0, 0, 0); "> is</span><s style="background - color: rgb(255, 255, 255); color: rgb(0, 0, 0); "> simply</s><em style="background - color: rgb(255, 255, 255); color: rgb(0, 0, 0); "> dummy<a href="https://www.naver.com/" rel="noopener noreferrer" target="_blank"> </a></em><a href="https://www.naver.com/" rel="noopener noreferrer" target="_blank" style="background-color: rgb(255, 255, 255); color: rgb(0, 0, 0);">text </a><span style="background-color: rgb(255, 255, 255); color: rgb(0, 0, 0);">of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem</span> Ipsum.</p><p><br></p><p><img src="https://img1.daumcdn.net/thumb/R1280x0.fjpg/?fname=http://t1.daumcdn.net/brunch/service/user/cnoC/image/66LHXQZY2bFLKR7SEO_KJjOnX6M" width="133" style=""></p><p><br></p><p><br></p>`
const sanitizedContent = DOMPurify.sanitize(dummyContent); //2.사용
//아래는 background - color로 태그가 들어와 오류가 나서 띄어쓰기를 제거하도록 로직을 추가했다.
const fixedContent = sanitizedContent.replace(/background\s*-\s*color/g, 'background-color');
return (
<div dangerouslySetInnerHTML={{ __html: fixedContent }}> //3.입력된 값 노출 적용
</div>
);
}
결과화면
+ 추가
에디터 내에서 video링크를 삽입한 태그가 노출되지 않았다.
DOMPurify에서 기존 코드를 안전하게 변경하느라 허용하지 않는 태그인 iframe도 걸러졌다.
따라서 별도로 iframe을 허용해주는 코드를 추가했다. 참고한 사이트
- ADD_TAGS: 허용할 태그
- ADD_ATTR: 허용할 속성
- allow: iframe 내에서 특정 기능을 사용할 수 있도록 허용하는 속성입니다.
- allowfullscreen: iframe이 전체 화면 모드로 전환될 수 있도록 허용합니다.
- frameborder: iframe의 테두리 설정을 정의합니다.
- scrolling: iframe 내에서 스크롤 가능 여부를 설정하는 속성입니다.
const sanitizedContent = DOMPurify.sanitize(dummyContent, { ADD_TAGS: ["iframe"], ADD_ATTR: ['allow', 'allowfullscreen', 'frameborder', 'scrolling'] });
결과화면
참고 사이트
'React' 카테고리의 다른 글
[React] React Quill 에디터 라이브러리 사용 5-수정 페이지 (0) | 2024.10.22 |
---|---|
[React] React Quill 에디터 라이브러리 사용 4-이미지 리사이즈(quill-image-resize) (1) | 2024.10.21 |
[React] React Quill 에디터 라이브러리 사용 3-이미지 처리/편집 완료 ✨(feat.react-quill-new) (4) | 2024.10.21 |
[React] React Quill 에디터 라이브러리 사용 2-이미지 처리/편집 중 (feat.react-quill-new) (0) | 2024.10.16 |
[React] React Quill 에디터 라이브러리 사용 1(feat.react-quill-new) (0) | 2024.10.15 |