【Laravel/PHP】改行コード(\n)は認識させたいけど、HTMLタグは文字列とて認識させたい

もくじ

したいこと(=タイトル)

タイトルの通りなんですが、改行コード(\n)は認識させたいけど、HTMLタグ(<scrip>タグなど)は文字列とて認識させたい!!ってことです。

なぜこれをするかというと、XSSクロスサイトスクリプティング)攻撃のターゲットにならないための対策です。

bonoponz.hatenablog.com

では次の変数の中身を出力させて確認してみます。

$data = "明日は\n運動会<br>です。<script>alert('スクリプト実行');</script>";

これを単純に表示すると下記のようになります。

<p>{{ $data }}</p>

f:id:bonoponz:20201001195844p:plain

それでは順番に見ていきます!

{!! !!}でHTMLタグをエスケープさせない

{!! !!}で囲むことでHTMLタグがエスケープされません。

bonoponz.hatenablog.com

$data = "明日は\n運動会<br>です。<script>alert('スクリプト実行');</script>";
<p>{!! $data !!}</p>

f:id:bonoponz:20201001194321p:plain

入力フォームにもしHTMLタグを入力された場合それをそのままHTMLタグとして読み込みます。

そのため、変数の中にあるスクリプトが実行してしまいます。また、スクリプト部分はスクリプトとして認識されるので出力もされず文字列だけが出力されます。

f:id:bonoponz:20201001194347p:plain

その上、\nはタグではないので改行とは認識されず、<br>は認識され改行されています。

nl2br関数で\n<br>に変換

bonoponz.hatenablog.com

$data = "明日は\n運動会<br>です。<script>alert('スクリプト実行');</script>";
<p>{!! nl2br($data) !!}</p>

f:id:bonoponz:20201001195555p:plain

f:id:bonoponz:20201001195609p:plain

スクリプトは実行されてしまいましたが、\n<br>に変換され改行して欲しいところですべて改行されていますね。

では次がようやく、本題です!

e()サニタイズ

XSSを防ぎながら改行を表示するにはe()を使って以下のように記述します。

$data = "明日は\n運動会<br>です。<script>alert('スクリプト実行');</script>";
<p>{!! nl2br(e($data)) !!}</p>

f:id:bonoponz:20201001202350p:plain

スクリプトは実行されず、改行コードで改行もされています。しかし、<br>もHTMLタグとして認識されるので改行されません。

解説

e()関数でまずHTMLタグを文字列にします。

<p>{!! e($data) !!}</p>

f:id:bonoponz:20201001202810p:plain

次に全体をnl2br関数に入れ、\nを改行させます。

<p>{!! nl2br(e($data)) !!}</p>

f:id:bonoponz:20201001202350p:plain

もし囲う順番を間違えると違う結果になります。

<p>{!! e(nl2br($data)) !!}</p>

f:id:bonoponz:20201001203337p:plain

使い分け

今回取り上げた方法を使って、その時に最適な記述をしましょう。

参考URL

【Laravel】改行を含む入力内容を表示する方法と注意点 | 働きたくないけどお金欲しい