質問するログイン新規登録

Q&A

解決済

5回答

3106閲覧

セキュリティ対策はフロントエンドだけではなくサーバーサイドでもすべきでしょうか?

homepage-site

総合スコア75

WordPress

WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

3クリップ

投稿2025/04/25 08:13

0

3

実現したいこと

新規登録|ログイン画面を PHP と Javascript で作成したい。

発生している問題・分からないこと

JavaScriptでメールアドレスの入力チェックを行い、6桁の確認コードをメールで送信したいのですが、以前フロントエンドはユーザーが入力したことに対してのものなので、セキュリティ対策としては足りないとアドバイスを頂き PHP 側でも同様のチェックを行うべきか悩んでおります。

該当のソースコード

Javascript

1 <style> 2 /* フォーカスが当たった時の青枠を表示しない */ 3 *:focus { 4 outline: none; 5 } 6 7 /* 項目名用のラベル(今回はラベルなしデザイン) 8 div.input-area label { 9 display: inline-block; 10 width: 8rem; 11 text-align: right; 12 } */ 13 14 /* エラーメッセージのスタイル */ 15 div.error-msg p { 16 color: #e52d77; 17 margin: 0 0 0 8rem; 18 } 19 20 /* 入力欄 */ 21 input[type="email"] { 22 line-height: 2em; 23 } 24 25 /* 入力エラーがあった時のスタイル(エラーがあった時は枠の色は分かりずらいので変更せずエラー文のみ表示させる) 26 .input-error { 27 border: 1px solid #e52d77; 28 border-radius: 3px; 29 background-color: #FCC; 30 } */ 31 32 /* クリック時に枠の色を変更 */ 33 ○○○:hover { 34 border: 2px solid #000; 35 } 36 </style> 37 38 39 <div class="login-email"> 40 <form method="post" class="register_form"> 41 <div class="form_item"> 42 43 <div class="login-inputWrapper"></div> 44 <!-- hiddenで生成したトークンを埋め込む --> 45 <!-- oninputプロパティは一定時間操作が無かったら処理を実行させる関数 --> 46 <input type="hidden" id="input-email" name="csrf_token" maxlength="15" oninput="value=value.replace(/[^\d]/g, '')" placeholder="メールアドレスを入力してください" value="<?= $csrf_token; ?>"> 47 <div id="error-msg-email" class="error-msg" style="display: none;"></div> 48 49 <div class="login-email_vertical-line"></div> 50 <div class="login-email-send clickable disabled"> 51 <font style="vertical-align: inherit;"> 52 <font style="vertical-align: inherit;">認証コードを取得する</font> 53 </font> 54 </div> 55 </div> 56 57 58 <div class="form__separator-line"></div> 59 <div class="form__item"> 60 <div> 61 <font style="vertical-align: inherit;"> 62 <font style="vertical-align: inherit;">検証コード</font> 63 </font> 64 </div><input placeholder="確認コードを入力してください" maxlength="6" oninput="value=value.replace(/[^\d]/g, '')"> 65 </div> 66 </form> 67 68 <script> 69 // メールアドレスの入力チェック 70 var inputEmail = document.getElementById('input-email'); 71 72 /** 73 * フォーカスが外れた場合のイベントハンドラ 74 */ 75 inputEmail.addEventListener('blur', function() { 76 // 入力されたメールアドレスを取得してトリム(データの不要な部分を削除し、必要な部分だけを残して値を設定し直す)して値を設定し直す 77 // 通常は値の設定前に文字列の先頭と末尾の空白を削除するためにトリムする必要があります。 78 inputEmail.value = inputEmail.value.trim(); 79 80 // 入力チェック 81 // カスタムバリデーション名 82 validate_email(); 83 }); 84 85 /** 86 * メールアドレスの入力チェック 87 */ 88 function validate_email() { 89 90 var val = inputEmail.value; 91 92 // 必須チェック 93 if (val == "") { 94 // エラーメッセージの作成 95 var err_msg = document.createElement('p'); 96 err_msg.textContent = 'メールアドレスが入力されていません。'; 97 98 // エラーメッセージの表示領域 99 // var err_msg_div = document.querySelectorAll('#error-msg-email'); 100 var err_msg_div = document.getElementById('error-msg-email'); 101 102 // エラーメッセージの表示領域を表示する 103 err_msg_div.style.display = "block"; 104 105 // エラーメッセージの表示領域にエラーメッセージを追加 106 err_msg_div.appendChild(err_msg); 107 108 // 入力欄にinput-errorクラスを追加(入力フォームの色を変更) 109 // input_email.setAttribute('class', 'input-error'); 110 111 return; 112 } 113 // メールアドレス形式チェック 114 var regex = new RegExp(/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/); 115 if (!regex.test(val)) { 116 // エラーメッセージの作成 117 var err_msg = document.createElement('p'); 118 err_msg.textContent = '無効なメールアドレスです。'; 119 120 // エラーメッセージの表示領域 121 var err_msg_div = document.getElementById('error-msg-email'); 122 123 // エラーメッセージの表示領域を表示する 124 err_msg_div.style.display = "block"; 125 126 // エラーメッセージの表示領域にエラーメッセージを追加 127 err_msg_div.appendChild(err_msg); 128 129 // 入力欄にinput-errorクラスを追加(入力フォームの色を変更) 130 // input_email.setAttribute('class', 'input-error'); 131 132 return; 133 } 134 } 135 136 /** 137 * フォーカスが当たった場合のイベントハンドラ 138 */ 139 input_email.addEventListener('focus', function() { 140 141 // input-errorクラスを削除 142 input_email.classList.remove('input-error'); 143 144 // エラーメッセージの表示領域を非表示にする 145 document.getElementById('error-msg-email').style.display = "none"; 146 147 // エラーメッセージを削除 148 document.getElementById('error-msg-email').children[0].remove(); 149 }); 150 </script>

PHP

1<?php 2session_start(); 3 4// 変数の宣言 5// $error_message = ''; 6$mail = ''; 7 8// エラーが発生している時の処理 9/* if (!empty($_SESSION['error_message'])) { 10 $error_message = $_SESSION['error_message']; 11 unset($_SESSION['error_message']); 12} */ 13 14// それぞれの変数に値を代入 15// PHPの値が空であれば 16if (!empty($_SESSION['mail'])) { 17 $mail = $_SESSION['mail']; 18 // セッション変数を削除 19 unset($_SESSION['mail']); 20} 21 22// 確認コードをメールで送信(6桁) 23if (!empty($_SESSION['code'])) { 24 $_SESSION['code'] = rand(100000, 999999); 25 // セッション変数を削除 26 unset($_SESSION['code']); 27} 28 29// テンプレートとなるhtmlファイルを読み込む 30// $html = file_get_contents('user_regist.html'); 31 32// htmlファイルの変更したい部分を変換する 33// $html = str_replace('#error_message#', htmlspecialchars($error_message), $html); 34// $html = str_replace('#mail#', htmlspecialchars($mail), $html); 35 36// 変換したhtmlを表示する 37// print($html); 38?>

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

メール送信に関するコードを調べたところ PHP側でもチェックされているものが多く、未入力チェックとメールアドレスチェック(preg_match)は必要なのではないかと思いました。

補足

※ 参考サイト
https://blog.take-it-easy.site/web-develop/validate-input-of-name/

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

TakaiY

2025/04/25 08:32

> JavaScriptでメールアドレスの入力チェック ここで何をチェックしていますか? > セキュリティ対策 ここで言うセキュリティ対策とはどのようなものを指していますか? > PHP 側でも同様のチェック ここではどのような「チェック」を行なうつもりでしょうか。
homepage-site

2025/04/25 09:20

TakaiY さん回答ありがとうございます。 JavaScriptでメールアドレスの入力チェックはフォーカスが外れた場合の処理になります。 PHP 側では未入力チェック、メールアドレスの型を正規表現で判定、危険文字列置換の3点を行う予定です。 ※ 参考サイト https://ok-engineering.net/article/9 https://qiita.com/wakahara3/items/ec8c9b6cbdfef78d3a64
TakaiY

2025/04/25 10:54

入力されたメールアドレスの文字列に対してサニタイズ等を行なうにあたって、サーバ側でも実施する必要があるかどうか?という質問でしょうか? であれば、既についている回答にあるとおりだと思います。
homepage-site

2025/04/25 13:01

TakaiY さん回答ありがとうございます。 サーバーサイドでも実装してみます。
tezcello

2025/04/25 13:51

> JavaScriptでメールアドレスの入力チェックを行い(略)セキュリティ対策としては足りないと 既に指摘もされていますが、入力チェックは単なるバリデーションでセキュリティ対策の一環ではありません。 それと、正規表現でメールアドレスを表す文字列として適切かを判断するのはとても難しいと読んだ記憶があります。 その正規表現で大丈夫ですか? __更に日本ではRFC違反のメールアドレスが横行していたはずですが、終息したのかなぁ? ご提示の正規表現が有効かの議論は脇に置くとして... 与えられた文字列がメールアドレスとして使えるモノであるかの判定をしたいのではなく、連絡先として使える有効な(=生きている)メールアドレスを取得したいのではありませんか? 個人的には前者は意味が無いと考えます。 メールアドレスを手入力させる方法は、他者に無関係のメールを送り付ける事が可能だし、コピペせずに本当に手入力すると一定の割合で(自身のメールアドレスなのに)入力ミスをします。 なので、メールアドレスを取得する際は実際にメールをやり取りして取得するのが最適だと考えています。 __空メールへの返信として登録用URLを返信するとか __その場でメールを送信して(メール内に書いた)トークンを入力させるとか...
homepage-site

2025/04/26 13:04

tezcello さん回答ありがとうございます。 JavaScript はバリデーションということで覚えておきます。 その場でメールを送信して(メール内に書いた)トークンを入力させる方法で考えており、認証コードを取得するボタンを押すことでトークンを送信するように進めております。 // 確認コードをメールで送信(6桁) if (!empty($_SESSION['code'])) { $_SESSION['code'] = rand(100000, 999999); // セッション変数を削除 unset($_SESSION['code']); }
TakaiY

2025/04/26 14:07

いろいろやりとりが行なわれていますが、まだ質問の内容は解決していないのでしょうか?
homepage-site

2025/04/26 14:22

TakaiY さん回答ありがとうございます。 申し訳ありません、解決いたしました。
tezcello

2025/04/26 15:38

> JavaScript はバリデーションということで覚えておきます。 JavaScriptでやっているクライアント上でのチェックはバリデーションではなくて、無駄な(サーバ側で明らかに拒否されてしまう)データ送信を防いでくれる単なる「お助け機能」って思っています。 クライアント側でやってもサーバ側で省略する事は出来ない訳だし、それを「バリデーション」なんて呼ぶとホントにバリデーション出来ているみたいに感じてしまいますから。 「お助け機能」は、無駄な送受信やサーバ側での処理が無くなるとか、入力の手間が無くなる(減る)とか、見栄えが良くなるとか、操作がし易くなるとかの利用者の利便性を高めるモノで、セキュリティとかバリデーションとかとは別物と考えるべきだろうなと。 __重複送信を回避するとかはセキュリティと言えなくもない気もするけど...
homepage-site

2025/04/28 06:56

tezcello さん回答ありがとうございます。 セキュリティではなくお助け機能という認識で覚えておきます。
otn

2025/04/28 09:07

> JavaScript はバリデーションということで覚えておきます。 とか、 > セキュリティではなくお助け機能という認識で覚えておきます。 とか、何故そんなに意味ないレベルにまで話を単純化したいのでしょうか? 単純化せずにそのまま理解しましょう。もしかすると「回答やコメントの内容が理解できないので、単純化して覚えるしかない」と最初から諦めてませんか?ブラウザのJavaScriptでは何をやり、サーバーサイドでは何をやるのかというのは、きちんと理解していないと設計できないです。
homepage-site

2025/04/28 09:58

otn さん回答ありがとうございます。 言葉足らずで申し訳ありません。 Javacript はユーザーの利便性を向上するものであり、セキュリティ対策の一環ではないという認識で覚えておきます。
TakaiY

2025/04/28 12:12

www > Javacript はユーザーの利便性を向上するものであり、セキュリティ対策の一環ではないという認識で覚えておきます。 違います。
utm.

2025/04/28 14:08

うーん。 おそらく質問者さん的に、 サイト運営者が意図していない行為や投稿はセキュリティの問題と考えているのでしょうが、それをセキュリティと呼ぶと文脈の誤解を誘発しやすく、意図的に使っているのであれば控えたほうがよさそうです。 例えば、入力は100文字までですという入力フィールドに101文字入れた人がいたらこれはセキュリティ的な問題、攻撃であるということを思っているのかもしれません。 それも考えとしては一理あるかもしれないのですが、ニュアンスとして「セキュリティ(?)」になってしまって、コミュニケーションが難しいなって感じもします。 バリデーションには二つの種類があります。 これはデータがただの状態であるケースがあるためです。 重複のバリデーションはまさにこれで、状態として成立しているかしていないかというものです。 逆に8文字以上入力できません。みたいなバリデーションは状態に関係なく常に行えます。 そのような観点から、入力時にクライアントPC(javascript)で検証できるもの、データの登録などに際してサーバーサイドで検証しなければならないものというのが発生し、どちらもバリデーションと呼ぶために誤解を受けやすいワードにもなっています。 (また、アプリサーバーの設計としてそもそも検証しなくてもDBがエラーしてくれることを信頼するとかいうのもあるので更に面倒。まあデータの登録が目的なAPIであれば役割としては理にかなっていると考えられますけども。) 根本的に質問者さんが理解できればすっといけそうなのは、通信だとかがただのデータのやり取りで、HTMLだのはただの見せかけでしかないということ。 裏側とか最小としてどういうことが起きるのかということを勉強することで質問内容もすっきりして、疑問の内容もすっきりして、自分で考えて結論を導く力がわくと思います。 最終的に何を目指しているのか分かりませんが、詰まるたびに対処療法的にやっていってもほんとにこの時しか使えないので、ちゃんと知識として蓄えていくことを目標にした方が健全な気もしています。 よく質問されているので実際に困っているとは思うのですがこういった情報からうまく学んでいくという意欲的な部分は少なめなんでしょうか。 これだけたくさんの人がご協力している形で CSRFやメールでの認証というそこまで難しくない概念で詰まるという状況がなんか不自然です。
TakaiY

2025/04/29 02:32

同感です。 用語だけなのかもしれませんが、1つ前のポストの「Javacript はユーザーの利便性を向上するもの」などのように主語が大きくて大雑把で、同様の傾向は質問にもあって、アドバイスしようとしている人たちとの認識のギャップがなかなか埋まらない感じがしますね。
guest

回答の取得に失敗しました

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.25%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問