画面上のテキストエリアにユーザーがHTML文字列を入力する仕様だが
scriptタグなどはXSSリスクがあるので入力できないようにする方法を書きます
実装方法
ポイントは入力されたHTML文字列をstringのままチェックするのではなく、
HTMLElementとしてチェックするところです
そのためテキストエリアの下に入力した文字列をHTMLとして描画し、その要素を取得してタグのチェックを行います
文字列のHTML描画はnpm install interweave
でhtmlを安全に描画できるライブラリをインストールします
import { Interweave } from "interweave";
import React, { useState } from "react";
// 入力可能なhtmlタグ
const allowedTags = ["p", "span", "div"];
const HtmlInput = () => {
/** 入力内容 */
const [text, setText] = useState("");
/** チェック結果メッセージ */
const [checkResult, setCheckResult] = useState("");
/**
* htmlタグチェック
*/
const checkTags = () => {
// interweaveでhtml描画している箇所のhtmlElementを取得する
// children[0]にはinterweaveにより追加されたspanが入ってくるので、更にその子要素が入力内容のhtmlとなる
const elements = document.getElementById("checkArea")?.children[0].children;
for (let i=0; i < elements!.length; i++){
// tagNameで取得したタグ名は大文字なので小文字化する
if (!allowedTags.includes(elements?.item(i)?.tagName!.toLowerCase()!)){
setCheckResult("チェックNG");
return false;
}
}
setCheckResult("チェックOK");
}
return (
<div>
<textarea value={text}
onChange={event => setText(event.target.value)}
onBlur={checkTags}>
</textarea>
<div id="checkArea" className="hidden">
<Interweave content={text}/>
</div>
<div>
{checkResult}
</div>
</div>
)
}
export default HtmlInput;