JavaScriptで特殊文字エスケープする3つの方法【htmlspecialchars的実装】

JavaScriptにはこういう関数はありません。

  • HTML特殊文字をエスケープできる関数
  • PHPのhtmlspecialchars的な関数

だから自作する必要があります。

いくつか方法があったので、
JSで特殊文字エスケープの方法をまとめました。

大前提.HTMLでエスケープすべき特殊文字とは

ググれば出てくるけど次の6つです。

  • 「&」 : アンパサンド
  • 「'」 : シングルクォート
  • 」 : アクサングラーブ,
  • 「"」 : ダブルクオート
  • 「<」 : 小なり記号
  • 「>」 : 大なり記号

関係ないけど 「」 ってアクサングラーブ(またはグレーブアクセント)と呼ぶらしいです。こんな名前があるとは知らなかった

これらをエスケープするのはXSS攻撃を防ぐためです。(XSS攻撃については次記事を参照 : https://pisuke-code.com/xss-attack-by-one-line-javascript/

これをJavaScriptでエスケープする方法について…

方法1.jQueryのtextメソッドとかを使う

限定的だけどオーソドックスな方法です。

jQueryのtextメソッドによるエスケープ

▼ このメソッドについての説明

We need to be aware that this method escapes the string provided as necessary so that it will render correctly in HTML. To do so, it calls the DOM method .createTextNode(), does not interpret the string as HTML.

引用元 : https://api.jquery.com/text/#text-text

この説明では「it will render correctly in HTML」=「HTMLを正しくレンダリングする」とあります。それも役割の1つですが、やっぱり参照文字をエスケープするのが目的です。

▼ 例えば こういう使い方をする

これはXSS攻撃を防ぐ手段の1つです。

ちなみに属性値の変更・追加にはattrメソッドが使われますが、そちらも特殊文字はエスケープしてくれます。その点はjQueryの親切なとこです。

ただし・・・直接HTMLから要素を作って追加する時にはこの関数は使えません。当然と言えばそうですが、用途は限られてきます。

方法2.特殊文字を正規表現でエスケープする

これはググるとよく出てくる方法です。

特殊文字全てをエスケープする関数を作るやり方

▼ こんな関数を作ればOK

▼ こんな風に使うことができる

実はある記事に載ってたコードをいくらか改変したものです、(Qiitaのこの記事 : https://qiita.com/saekis/items/c2b41cd8940923863791

これはどんな場合にも使える汎用的な方法です。

方法3.createTextNodeで特殊文字をエスケープ

最後は少し変わってるけど楽な方法です。

  • 臨時的なテキストノード作成
  • そこにエスケープしたいテキスト代入
  • 臨時的な要素にそれを突っこむ
  • 要素HTMLを取得すればエスケープ完了

言葉で書くと分かりにくいかも(-_-;) これはcreateTextNodeで仮のテキストノードを作り、なんやかんやして特殊文字をエスケープするやり方です。

▼ こういう関数を作ってみた

▼ 使い方は方法2と同じ

まず document.createTextNode(unsafeText)  から臨時的なテキストノードを作ります。それを仮のp要素に突っこみ、最後に p.innerHTML  からエスケープされた内容を返すって感じ

これでも立派に特殊文字エスケープできます。

方法2か方法3はどっちを使ってもOKです。

JSでの特殊文字エスケープ方法のまとめ

ここまで紹介した3つを箇条書き

  1. jQueryのtextメソッドとかを使う
    実はjQueryのtextメソッドとかattrメソッドには元々エスケープ機能がある。ただしHTMLから直接要素を作って追加する時とかには使えない
  2. 特殊文字を正規表現でエスケープする
    エスケープが必要な文字を正規表現を使って置き換える。自分でどの文字をエスケープすべきかの判断は必要だが、ググればベストな作り方を知るのは容易
  3. 特殊文字をcreateTextNodeでエスケープ
    臨時的なテキストノードを作成し、そこにエスケープしたいHTMLを代入。さらに臨時的な要素にテキストノードを突っこみ、内部HTMLを取得してエスケープ完了

このどれかを使っておけばOKなはずです。

もし間違いがあればご指摘ください。ではまた(@^^)/~~~