初心者向け。セキュリティ対策を含んだPHPのお問い合わせフォーム
2768 回閲覧されました
みなさんこんにちは、jonioです。
PHPでセキュリティ対策を含むお問い合わせフォームを作るための情報を探して実装したのですがアウトプットの記事を残します。
それでは説明します。
目次
作成時の注意点
仮想環境では動かない(MAMPやXAMPPならあるけどやり方が面倒すぎるからやめた方がいい)ので本番環境でやってください。
Herokuで動かそうとしたのですが何かの設定がないのが原因だと思いますがエラーになって動きませんでした。
セキュリティの内容
どんなセキュリティを入れればいいかが分からなかったのでネットで調べたのですが下記の内容を入れればとりあえず大丈夫だろうということになりました。
- XSS(クロスサイトスクリプティング)
- CSRF(クロスサイトリクエストフォージェリ)
XSSの内容はこの記事に説明があってCSRFはこの記事に説明があります。
実装内容
ファイルを「index.php」・「confirm.php」・「complete.php」の3つに分けます。
ファイルの役割は下記になります。
- index.php:フォームがある画面
- confirm.php : 確認画面
- complete.php : お問い合わせの送信完了の画面
それぞれのファイルの実装内容は下記になります。
index.php
- フォームの内容を設置
- CSRF対策の為のフォームがあるページ(index.php)を表示するたびに生成されるワンタイムトークン(パスワードみたいな物)の発行
confirm.php
- フォームに記入した内容でいいかの表示
- 修正する場合のフォームページに戻るボタンの設置
- 直接URLの指定からこのページに来たもしくは正しいトークンではない場合のリダイレクト処理
complete.php
- お問合せが完了したことを表示
- 自動返信メールの設定
- 直接URLの指定からこのページに来たもしくは正しいトークンではない場合のリダイレクト処理
それではそれぞれのページを作成します。
まずはindex.phpから作成しますがCSSは全てのページで同じなので最初に記載します。
index.php
まずはセキュリティがないコードにします、↓です。
これで↓になります。
10行目に「method=”POST”」がありますがフォームの内容がURLに追加されるのはセキュリティ上よくないので「POST」にしています。
「method=”〜”」の「〜」はPOSTかGETがありますが↓の記事で違いを解説しています。
10行目の「action=”confirm.php”」は次のページをconfirm.php(確認のページ)にするためです。
confirm.phpに移す情報は下記になります。
- 14行目の「name=”name“」のname
- 18行目の「name=”email“」のemail
- 22・23行目の「name=”sex“」のsex
- 27行目の「name=”pref“」のpref
- 36行目〜40行目の「name=”reason[]“」のreason[](配列になっている理由は後で説明します)
- 44行目の「name=“contact_body“」のcontact_body
- 47行目の「name=”submit“」のsubmit
- フォームに入力した内容とチェックボックスにチェックを入れた内容をconfirm.php(確認画面)で表示しますがその時にxss対策の実装をします。
それではindex.phpにCSRF対策をします。
コードを↓にします。
5行目でセッションを使っているのはフォームに入力したりチェックボックスのチェックした内容を複数ページに渡って渡すことができるようにするためです。(セッションがないと次のページまでしか情報を渡すことはできません)
7行目と8行目でトークンの発行をしていますが32桁がセキュリティ上安全みたいです。
セキュリティに関してはこの記事に情報がまとめてあると思います。
10行目で発行したトークンをセッションに保存しています。
発行したトークンですがcomfirm.php(確認のページ)に情報を渡さないとそのページで使うことができなく使うことができるようにするため63行目があります。
次はconfirm.php(確認のページ)です。
confirm.php
普通はフォームに入力とチェックをしてこのページに来ますが中には直接URLを入力したり不正なやり方でこのページに来る人もいるかもしれません。
そんな人はこのページに入ることができないようにするためにコードを↓にします。
「$_SERVER[“REQUEST_METHOD“] != “POST“」がURLを直接指定して確認ページに来た場合で「!isset($_POST[‘csrf_token’])」がトークンがない場合で「$_POST[‘csrf_token’] != $_SESSION[‘csrf_token’])」が正しいトークンではない場合です。
4行目・5行目がリダイレクトの処理です。
それではXSS対策をして確認内容が表示されるための記述をしますがコードを↓にします。
これで↓になります。(index.phpで入力とチェックをしています)
10行目〜15行目はフォームに入力するページ(index.php)の情報を受け取っています。
15行目ですがindex.phpの「name=”reason[]”」(index.phpの50行目〜54行目)の値を受け取っています。
チェックした内容を複数受け取る事ができるようにするにはindex.phpの50行目〜54行目の様に「名称[ ]」とします。(今はreason[ ]です)
そしてチェックした情報を受け取るページ(今だとconfirm.php)で「implode(‘/‘, $_POST[‘reason’])」とすることで受け取った情報が複数ある場合は「/」で区切りを付けて表示できます。(例えば質問 / ご意見ご要望みたいな感じ)
受け取った内容を38行目・43行目・48行目・53行目・58行目・63行目で表示していますが「htmlspecialchars(〜,ENT_QUOTES,‘UTF-8’)」がXSS対策です。
68行目〜74行目はtype属性をhiddenにしていますが次のページcomplete.phpに情報を渡すための記述です。
66行目ですが「onclick=’history.back()‘」で「戻る」ボタンをクリックした時に1つ前のページに戻ることができるようになります。
それではお問合せ完了のページ(complete.php)を作ります。
お問合せ完了のページ(complete.php)
confirm.phpの時と同じ様に最初は確認ページと同じ様に直接URLを入力したり不正なやり方でこのページに来る人もいるかもしれません。
そんな人はこのページに入ることができないようにするためにコードを↓にします。
次はお問合せが完了した時の自動返信メールの設定をするためにコードを↓にします。
8行目・9行目は日本語の設定です。
自動返信メールは44行目でできますが書き方は「mb_send_mail(宛先, 件名, メッセージ, ヘッダ)」でmb_send_mail( )を使う時は必ず8行目と9行目の記述がないといけません。
宛先・件名・ メッセージ・ ヘッダの対応は以下になります。
- 宛先 : 12行目の「$to = $_POST[‘email’];」
- 件名 : 14行目の「$subject = “お問い合わせありがとうございます。“;」
- メッセージ : 16行目〜40行目
- ヘッダ : 42行目の「$headers = “From: support@example.com“;」(「support@example.com」は送信先のメールアドレスにする)
16行目の「<<< EOM」から40行目の「EOM;」までをヒアドキュメントといって「<<< EOM」〜「EOM;」の〜の部分をそのまま表示できます。
例えば↓です。
「EOM」ですがこの文字は何でもよくて多いのは「EOM」・「EOF」・「EOD」みたいです。
それぞれは略称ですが↓が一覧になります。
- EOM : End Of Message
- EOF : End Of File
- EOD : Enf Of Document
最後に完了画面の表示をしますがコードを↓にします。
これで画面が↓になります。
これで完成です。