前回は、
Warning: Undefined array key "name"
という警告について調べました。
そして、
$name = $_POST['name'] ?? '';
とすることで、
「nameが送られていなければ、空の文字を使う」
という処理ができることを知りました。
では、フォームを完成させてみましょう。
<form method="post">
<input type="text" name="name">
<button type="submit">送信</button>
</form>
PHP側はこうします。
<?php
$name = $_POST['name'] ?? '';
if ($name !== '') {
echo 'こんにちは、' . $name . 'さん';
}
名前に、
みのり
と入力して送信すると、
こんにちは、みのりさん
と表示されます。
よし。
今度こそ完成!
……でしょうか?
名前じゃないものを入力してみる
せっかくなので、少し変な文字を入力してみましょう。
名前の代わりに、
<b>みのり</b>
と入力して送信してみます。
普通に考えれば、
こんにちは、<b>みのり</b>さん
と表示されてほしいところです。
ところがブラウザでは、
こんにちは、みのりさん
と、「みのり」の部分が太字になって表示されることがあります。
なぜでしょう?
ブラウザがHTMLとして読んでしまった
今回入力した、
<b>みのり</b>
には、
<b>
と、
</b>
があります。
これはHTMLで、
この間の文字を太字として扱う
という意味を持つタグです。
つまり現在のPHPは、
入力された文字をそのままHTMLの中へ出力している
ため、ブラウザが入力内容までHTMLとして解釈してしまったわけです。
「太字になるだけなら別にいいのでは?」
今回の例だけを見ると、
文字が太字になっただけじゃん。
と思うかもしれません。
でも、ここで少し考えてみましょう。
ユーザーが入力できる文字を、そのままWebページへ出力できる。
ということは、
こちらが想定していないHTMLまで入力される可能性がある
ということです。
そして、Webページで扱われるのはHTMLだけではありません。
JavaScriptもあります。
入力された内容を無条件にHTMLとして扱わせる設計は、場合によっては**クロスサイトスクリプティング(XSS)**と呼ばれる脆弱性につながります。
ここでは、攻撃方法を覚える必要はありません。
今日覚えておきたいのは、
外から入力された文字を、そのままHTMLとして表示するのは危険な場合がある。
これだけです。
今日の合格ライン
今回はここが分かれば合格です。
フォームに入力された文字を、そのままHTMLへ出力しない。
PHPでフォームを作っていると、
echo $name;
のようなコードはよく登場します。
でも、
その
$nameはどこから来たデータ?
と、一度考える癖をつけましょう。
自分でプログラム内に設定した文字なのか。
ユーザーがフォームに入力した文字なのか。
外部から取得したデータなのか。
データがどこから来たのかを見る。
これは、AIが書いたコードを確認するときにも重要です。
AIに聞いてみよう
今回も、分からなければAIに相談してみます。
たとえば、
PHPでフォームに入力された名前をechoで表示しています。
HTMLタグのような文字を入力すると、ブラウザがHTMLとして解釈してしまいます。
ユーザーが入力した文字を安全に表示する基本的な方法を、初心者向けに教えてください。
すると、おそらくこんな関数が出てきます。
htmlspecialchars()
……長い。
でも大丈夫です。
暗記しなくてOKです。
何をしているのかだけ見てみましょう。
htmlspecialchars() を使ってみる
先ほどのコードを少し変更します。
<?php
$name = $_POST['name'] ?? '';
if ($name !== '') {
echo 'こんにちは、'
. htmlspecialchars($name, ENT_QUOTES, 'UTF-8')
. 'さん';
}
急に難しそうになりました。
今回見るのは、ここだけです。
htmlspecialchars($name, ENT_QUOTES, 'UTF-8')
ものすごく簡単に言えば、
HTMLとして特別な意味を持つ文字を、そのまま文字として表示できる形に変換する
ための処理です。
もう一度 <b>みのり</b> を入力する
先ほどと同じ、
<b>みのり</b>
を送信してみます。
今度はブラウザに、
こんにちは、<b>みのり</b>さん
と表示されます。
太字にはなりません。
<b> という文字そのものが表示されています。
つまりブラウザに、
「これはHTMLタグじゃないよ。普通の文字として表示してね」
と伝えられたわけです。
中では何が起きている?
HTMLには、特別な意味を持つ文字があります。
たとえば、
<
>
&
"
'
などです。
htmlspecialchars() は、こうした文字をHTMLで安全に文字として扱える表現へ変換してくれます。
たとえば、
<
なら、HTML上では、
<
のような形になります。
ブラウザはこれを画面上では、
<
として表示します。
つまり、
見た目は < だけど、HTMLタグを開始する < としては扱われない
というわけです。
ENT_QUOTES と UTF-8 は何?
AIにコードを書いてもらうと、
htmlspecialchars($name, ENT_QUOTES, 'UTF-8')
のように、さらに知らないものが付いてくることがあります。
ここも今はざっくりでOKです。
ENT_QUOTES は、
シングルクォートやダブルクォートも変換対象にする
ための指定。
UTF-8 は、
この文字列をUTF-8として扱う
という指定です。
日本語のWebサイトではUTF-8が広く使われています。
今の段階では、
htmlspecialchars($name, ENT_QUOTES, 'UTF-8')
を見て、
「あ、画面に安全に文字を出すための処理かな」
と気付ければ十分です。
「入力するとき」に変換するの?
ここは少し重要です。
たとえば名前を受け取った直後に、
$name = htmlspecialchars($_POST['name'] ?? '', ENT_QUOTES, 'UTF-8');
としてしまうコードを見かけることもあります。
小さなサンプルでは動きます。
ただ、
「受け取った瞬間に何でもHTML用に変換すればいい」
と覚えるのはおすすめしません。
htmlspecialchars() は基本的に、
HTMLへ出力するとき
に必要になる処理だからです。
同じデータをメールに使うかもしれない。
データベースへ保存するかもしれない。
CSVへ出力するかもしれない。
使う場所によって、必要な安全対策は変わります。
なので今は、
HTMLへ表示するときは、HTMLへ表示するための安全対策をする。
と覚えておきましょう。
AIが書いたコードでも、安全とは限らない
ここが今回、一番大切なところかもしれません。
AIに、
「PHPで名前を入力して表示するフォームを作って」
とお願いすれば、数秒でコードを書いてくれます。
しかも、ちゃんと動くことも多いです。
でも、
動くコード=安全なコード
とは限りません。
だからAIが出したコードを見るとき、
この入力値はどこから来ている?
そのまま画面に出していない?
ユーザーが変な文字を入力したらどうなる?
と考えられるだけでも、大きな違いがあります。
コードを全部自分で書けなくても構いません。
「ここ、大丈夫?」とAIに質問できること。
それも立派なWeb制作の力です。
AIへの質問を一段階進めてみる
最初なら、
このPHPフォームを作って。
だけでもOKです。
でも今回のことを知ったなら、次はこう聞けます。
PHPで名前を入力して表示するフォームを作ってください。
ユーザーからの入力値をHTMLへ表示するときの安全対策も入れてください。
また、なぜその処理が必要なのか初心者向けに説明してください。
さらに、すでにAIがコードを書いてくれたなら、
このコードで、ユーザーから受け取った値をそのままHTMLへ出力している箇所はありますか?
XSSなどの問題につながる可能性がないか確認してください。
と聞くこともできます。
知識が一つ増えると、AIへの質問も一つ良くなる。
これを積み重ねていけばOKです。
ワンポイント:htmlspecialchars() を使えば全部安全?
ここも大切です。
いいえ。
htmlspecialchars() はとても重要ですが、
これを付ければ、あらゆるセキュリティ問題が解決する魔法の関数
ではありません。
HTMLのどこへ値を出すのか。
JavaScriptで使うのか。
URLとして使うのか。
データベースへ保存するのか。
用途によって対策は変わります。
今回はあくまで、
ユーザーから受け取った文字列をHTML本文へ文字として表示する
という場面を扱っています。
セキュリティは一気に全部覚えなくて大丈夫です。
必要になった場面で、一つずつ覚えていきましょう。
3話で、ここまで読めるようになった
最初に見たコードを、もう一度見てみます。
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
if ($name !== '') {
echo 'こんにちは、'
. htmlspecialchars($name, ENT_QUOTES, 'UTF-8')
. 'さん';
}
}
第1話の時点では、
「何これ?」
だったかもしれません。
でも、今ならどうでしょう。
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
POSTされたときだけ動かしている。
$name = $_POST['name'] ?? '';
送られてきた name を受け取って、なければ空にする。
if ($name !== '') {
名前が空じゃなければ、
htmlspecialchars($name, ENT_QUOTES, 'UTF-8')
HTMLへ安全に文字として表示できるようにして、
echo
画面へ表示する。
なんとなく読める。
それで十分です。
最初から全部書けなくてもいい。
AIに書かせてもいい。
検索してもいい。
コピペしてもいい。
でも、
「このコード、だいたい何をやっているんだろう?」
が少しずつ分かるようになっていく。
それが今回の合格です。
次は「送信したらページが真っ白」?
フォームについて少し分かってきました。
では次は、WordPressでもPHPでもかなり遭遇する、
「変更したら画面が真っ白になった」
を扱ってみましょう。
500エラーとは何が違うのか。
なぜ何も表示されないのか。
そして、何も表示されていない状態から、どうやって原因を探すのか。
次回は、
何も表示されない!PHPの「真っ白な画面」はどう調べる?
です。
