
ブログつくるときにちょうどよかったやつです.このブログにも採用しています.※このブログのコードはここにあります概要ユーザがエディタなどで作成したHTMLを画面上に表示することを考えます.入力として,文字列としてのHTMLがstring型で与えられて,それをパースして表示することを考えます.イメージとしては,次のようなコードです.const userContents = () => {
const html = "<h1>Hello World</h1><p>こんにちは</p>"
return <div> {/* ここにhtmlを展開 */}<div>
}
いちばん危険で簡単な方法は,divタグ内でdangerouslySetInnerHTMLを用いて,htmlを表示することですが,XSS攻撃のリスクがあり,使うべきではありません.特にUGC(User Generated Content)に対しては,ユーザが入力したコンテンツに対するサニタイズ(無毒化)処理は必須です.実装安全にユーザが入力したHTMLを表示する際は,次の手順を踏みます.ユーザが入力したHTMLをサニタイズ(無毒化)サニタイズしたHTMLをReactで表示(Optional)スタイルを整えるユーザが入力したHTMLをサニタイズサニタイズにはDOMPurifyが利用できます.利用例としては次のとおりです.const sanitizedHtml = DOMPurify.sanitize(html);サニタイズしたHTMLをReactで表示Reactで表示する場合は,先述したdangerouslySetInnerHTMLを利用することができます.なお,必ずサニタイズしていることを確認する必要があります.const userContents = () => {
const dangerousHtml = "<h1>Hello World</h1><p>こんにちは</p>"
const sanitizedHtml = DOMPurify.sanitize(dangerousHtml);
const markup = {
__html: sanitizedHtml
}
return <div dangerouslySetInnerHTML={markup}><div>
}もし,dangerouslySetInnerHTMLを利用することに抵抗がある場合は,html-react-parserがおすすめです.html-react-parserを用いると次のように書けます.import DOMPurify from "isomorphic-dompurify";
import parse from "html-react-parser";
function contentsElem() {
const dangerousHtml = "<h1>Hello World</h1><p>こんにちは</p>"
const sanitizedHtml = DOMPurify.sanitize(dangeroushtml);
return parse(sanitizedHtml);
}
const userContents = () => {
return <div>{contentsElem}<div>
}(Optional) スタイルを整えるtailwindCSSを利用している場合,h1タグやpタグのサイズがだいたい同じくらいのサイズになり,あまりいい感じじゃないです.taiwindlabs/tailwindcss-typographyを利用すると,このへんのデザインがいい感じになります.tailwindCSSはclassNameにclassを書き込むことでスタイルが適用できます.tailwindcss-typographyの恩恵を受ける際はproseクラスを付与します.import DOMPurify from "isomorphic-dompurify";
import parse from "html-react-parser";
function contentsElem() {
const dangerousHtml = "<h1>Hello World</h1><p>こんにちは</p>"
const sanitizedHtml = DOMPurify.sanitize(dangeroushtml);
return parse(sanitizedHtml);
}
const userContents = () => {
return <div className="prose">{contentsElem}<div>
}だいたいいい感じになると思います.ご指摘などありましたらお気軽にお願いいたします.