質問編集履歴

3

質問の修正

2025/04/28 10:40

投稿

homepage-site
homepage-site

スコア70

test CHANGED
@@ -1 +1 @@
1
- 新規登録画面からメールアドレスに認証コードとユーザーネームを送る場合セキュリティ対策として確認画面を設けるべきでしょうか?
1
+ 会員登録画面から直接メールアドレスに認証コードを送る場合セキュリティ対策として確認画面を設けるべきでしょうか?
test CHANGED
@@ -1,63 +1,71 @@
1
1
  ### 実現したいこと
2
- 安全な方法で新規登録画面からメールアドレスにを送りたい。
2
+ 会員登録画面からメールアドレスに認証コを送りたい。
3
3
 
4
4
  ### 発生している問題・分からないこと
5
- 新規登録画面からメール送信に進むパターンと新規登録画面から入力された文字をチェックし非同期通信で確認画面に移動して、確認画面からメール送信に進むパターンのどちらがセキュリティ上良いでしょうか?
5
+ 以前お問い合わせページを作成した際に CSRF対策として入力画面からワンイムトを作成して、確認画面でそのトークンが一致するどうかをチェックするという仕組みを作成たのですが会員登録画面(入力画面からメールアドレスにイミングでワンタイムトを作成してチェックするとうことは可能でしょうか?
6
6
 
7
7
 
8
8
 
9
9
  ### 該当のソースコード
10
10
 
11
+ ```HTML
12
+ <div class="login-email">
13
+ <form method="post" class="register_form">
14
+ <div class="form_item">
15
+
16
+ <!-- <div class="login-inputWrapper"></div> -->
17
+ <!-- hiddenで生成したトークンを埋め込む -->
18
+ <!-- oninputプロパティは一定時間操作が無かったら処理を実行させる関数 -->
19
+ <input type="hidden" id="input-email" name="csrf_token" maxlength="15" oninput="value=value.replace(/[^\d]/g, '')" placeholder="メールアドレスを入力してください" value="<?= $csrf_token; ?>">
20
+
21
+ <div id="error-msg-email" class="error-msg" style="display: none;"></div>
22
+
23
+ <div class="login-email_vertical-line"></div>
24
+ <div class="login-email-send clickable disabled">
25
+ <font style="vertical-align: inherit;">
26
+ <font style="vertical-align: inherit;">認証コードを取得する</font>
27
+ </font>
28
+ </div>
29
+ </div>
30
+
31
+ <div class="form_separator-line"></div>
32
+ <div class="form_item">
33
+ <div>
34
+ <font style="vertical-align: inherit;">
35
+ <font style="vertical-align: inherit;">ハンドルネーム</font>
36
+ </font>
37
+ </div><input placeholder="ハンドルネームを入力してください" maxlength="6" oninput="value=value.replace(/[^\d]/g, '')">
38
+ </div>
39
+
40
+ <div class="form_separator-line"></div>
41
+ <div class="form_item">
42
+ <div>
43
+ <font style="vertical-align: inherit;">
44
+ <font style="vertical-align: inherit;">検証コード</font>
45
+ </font>
46
+ </div><input placeholder="確認コードを入力してください" maxlength="6" oninput="value=value.replace(/[^\d]/g, '')">
47
+ </div>
48
+ <input type="hidden" name="csrf_token" value="<?php echo $csrf_token; ?>" />
49
+ <!-- ↑追加 -->
50
+ <!-- </div> -->
51
+ </form>
52
+ </div>
53
+ ```
54
+
11
55
  ```PHP
12
56
  <?php
13
- // 入力受け取り
14
- $name = $_POST['name'];
15
- $mail = $_POST['mail'];
16
-
17
- // string は $mail という引数が「文字列型」であることを表しています。
18
- // : bool は「この関数は 戻り値(returnする値)として、boolean型(trueかfalse)を返しますよ」という意味です。
19
- // 「文字列 $mail を受け取って、結果を真偽値(true または false)で返す関数」という宣言になります
20
- function checkmail(string $mail): bool
21
- {
22
- // 文字列 $mail を \`@\` を区切り文字として分割し、その結果を配列 $array に格納します。つまり、メールアドレスをユーザー名とドメインに分割します。
23
- $array = explode('@', $mail);
24
- // 配列 array の最後の要素の値を取り出して返します
25
- $domain_part = array_pop($array);
26
- // Filter 関数 の filter_var と ネットワーク関数 の checkdnsrr を利用してバリデーションを実装
27
- // FILTER_VALIDATE_EMAIL は RFC 822 に準拠しているメールアドレスか否かを検証します。
28
- // ネットワーク関数 の checkdnsrr を利用します。第二引数の DNS レコードの種類には、MX, A, AAAA を指定します。又、第二引数の既定値は MX です。
29
- // これで、メール送信の可不可を確認することができます。
30
- return filter_var($mail, FILTER_VALIDATE_EMAIL) !== false &&
31
- (checkdnsrr($domain_part) || checkdnsrr($domain_part, 'A') || checkdnsrr($domain_part, 'AAAA'));
32
- }
33
-
34
- // 先頭から末尾まで、文字(漢字・ひらがな・英字)、数字、スペース、ハイフンだけで構成されているかチェックする
35
- if (!preg_match('/^[\p{L}\p{N}\s\-]+$/u', $name)) {
36
- die('不正な名前です');
37
- }
38
-
39
- // サニタイズ(タグ除去)
40
- $name = strip_tags($name);
41
-
42
- // メール内容
43
- $subject = "DMM:会員登録認証メール";
44
- $message = "お名前: {$name}\nメールアドレス: {$email}\nお問い合わせを受け付けました。";
45
-
46
- // メールヘッダ(テキストメール指定)
47
- $headers = "From: noreply@example.com\r\n";
48
- $headers .= "Content-Type: text/plain; charset=UTF-8";
49
-
50
- // メール送信
51
- mail($email, $subject, $message, $headers);
52
-
53
- /* ======================================================================================================== */
54
-
55
57
  $_SESSION = array(); //セッション変数の初期化
56
58
  session_start(); //セッションの開始
57
59
 
58
60
  // 変数の宣言
59
61
  // $error_message = '';
60
62
  $mail = '';
63
+
64
+ // エラーが発生している時の処理
65
+ /* if (!empty($_SESSION['error_message'])) {
66
+ $error_message = $_SESSION['error_message'];
67
+ unset($_SESSION['error_message']);
68
+ } */
61
69
 
62
70
  // ワンタイムトークン生成
63
71
  $toke_byte = openssl_random_pseudo_bytes(16);
@@ -98,172 +106,6 @@
98
106
  ?>
99
107
  ```
100
108
 
101
- ```Javascript
102
- <div class="bili-mini-login-right-wp">
103
- <div data-v-35ff7abe="" class="login-tab-wp">
104
- <div data-v-35ff7abe="" class="login-tab-item">
105
- <font style="vertical-align: inherit;">
106
- <font style="vertical-align: inherit;">パスワードログイン</font>
107
- </font>
108
- </div>
109
- <div data-v-35ff7abe="" class="login-tab-line"></div>
110
- <div data-v-35ff7abe="" class="login-tab-item active-tab">
111
- <font style="vertical-align: inherit;">
112
- <font style="vertical-align: inherit;">SMSログイン</font>
113
- </font>
114
- </div>
115
- </div>
116
-
117
- <style>
118
- /* フォーカスが当たった時の青枠を表示しない */
119
- *:focus {
120
- outline: none;
121
- }
122
-
123
- /* エラーメッセージのスタイル */
124
- div.error-msg p {
125
- color: #e52d77;
126
- margin: 0 0 0 8rem;
127
- }
128
-
129
- /* 入力欄 */
130
- input[type="email"] {
131
- line-height: 2em;
132
- }
133
-
134
- /* クリック時に枠の色を変更 */
135
- ○○○:hover {
136
- border: 2px solid #000;
137
- }
138
- </style>
139
-
140
-
141
- <div class="login-email">
142
- <form method="post" class="register_form">
143
- <div class="form_item">
144
-
145
- <!-- <div class="login-inputWrapper"></div> -->
146
- <!-- hiddenで生成したトークンを埋め込む -->
147
- <!-- oninputプロパティは一定時間操作が無かったら処理を実行させる関数 -->
148
- <input type="hidden" id="input-email" name="csrf_token" maxlength="15" oninput="value=value.replace(/[^\d]/g, '')" placeholder="メールアドレスを入力してください" value="<?= $csrf_token; ?>">
149
-
150
- <div id="error-msg-email" class="error-msg" style="display: none;"></div>
151
-
152
- <div class="login-email_vertical-line"></div>
153
- <div class="login-email-send clickable disabled">
154
- <font style="vertical-align: inherit;">
155
- <font style="vertical-align: inherit;">認証コードを取得する</font>
156
- </font>
157
- </div>
158
- </div>
159
-
160
- <div class="form_separator-line"></div>
161
- <div class="form_item">
162
- <div>
163
- <font style="vertical-align: inherit;">
164
- <font style="vertical-align: inherit;">ハンドルネーム</font>
165
- </font>
166
- </div><input placeholder="ハンドルネームを入力してください" maxlength="6" oninput="value=value.replace(/[^\d]/g, '')">
167
- </div>
168
-
169
- <div class="form_separator-line"></div>
170
- <div class="form_item">
171
- <div>
172
- <font style="vertical-align: inherit;">
173
- <font style="vertical-align: inherit;">検証コード</font>
174
- </font>
175
- </div><input placeholder="確認コードを入力してください" maxlength="6" oninput="value=value.replace(/[^\d]/g, '')">
176
- </div>
177
- <input type="hidden" name="csrf_token" value="<?php echo $csrf_token; ?>" />
178
- <!-- ↑追加 -->
179
- <!-- </div> -->
180
- </form>
181
-
182
- <script>
183
- // メールアドレスの入力チェック
184
- var inputEmail = document.getElementById('input-email');
185
-
186
- /**
187
- * フォーカスが外れた場合のイベントハンドラ
188
- */
189
- inputEmail.addEventListener('blur', function() {
190
- // 入力されたメールアドレスを取得してトリム(データの不要な部分を削除し、必要な部分だけを残して値を設定し直す)して値を設定し直す
191
- // 通常は値の設定前に文字列の先頭と末尾の空白を削除するためにトリムする必要があります。
192
- inputEmail.value = inputEmail.value.trim();
193
-
194
- // 入力チェック
195
- // カスタムバリデーション名
196
- validate_email();
197
- });
198
-
199
- /**
200
- * メールアドレスの入力チェック
201
- */
202
- function validate_email() {
203
-
204
- var val = inputEmail.value;
205
-
206
- // 必須チェック
207
- if (val == "") {
208
- // エラーメッセージの作成
209
- var err_msg = document.createElement('p');
210
- err_msg.textContent = 'メールアドレスが入力されていません。';
211
-
212
- // エラーメッセージの表示領域
213
- // var err_msg_div = document.querySelectorAll('#error-msg-email');
214
- var err_msg_div = document.getElementById('error-msg-email');
215
-
216
- // エラーメッセージの表示領域を表示する
217
- err_msg_div.style.display = "block";
218
-
219
- // エラーメッセージの表示領域にエラーメッセージを追加
220
- err_msg_div.appendChild(err_msg);
221
-
222
- // 入力欄にinput-errorクラスを追加(入力フォームの色を変更)
223
- // input_email.setAttribute('class', 'input-error');
224
-
225
- return;
226
- }
227
- // メールアドレス形式チェック
228
- var regex = new RegExp(/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/);
229
- if (!regex.test(val)) {
230
- // エラーメッセージの作成
231
- var err_msg = document.createElement('p');
232
- err_msg.textContent = '無効なメールアドレスです。';
233
-
234
- // エラーメッセージの表示領域
235
- var err_msg_div = document.getElementById('error-msg-email');
236
-
237
- // エラーメッセージの表示領域を表示する
238
- err_msg_div.style.display = "block";
239
-
240
- // エラーメッセージの表示領域にエラーメッセージを追加
241
- err_msg_div.appendChild(err_msg);
242
-
243
- // 入力欄にinput-errorクラスを追加(入力フォームの色を変更)
244
- // input_email.setAttribute('class', 'input-error');
245
-
246
- return;
247
- }
248
- }
249
-
250
- /**
251
- * フォーカスが当たった場合のイベントハンドラ
252
- */
253
- input_email.addEventListener('focus', function() {
254
-
255
- // input-errorクラスを削除
256
- input_email.classList.remove('input-error');
257
-
258
- // エラーメッセージの表示領域を非表示にする
259
- document.getElementById('error-msg-email').style.display = "none";
260
-
261
- // エラーメッセージを削除
262
- document.getElementById('error-msg-email').children[0].remove();
263
- });
264
- </script>
265
- ```
266
-
267
109
  ### 試したこと・調べたこと
268
110
  - [x] teratailやGoogle等で検索した
269
111
  - [x] ソースコードを自分なりに変更した
@@ -271,10 +113,10 @@
271
113
  - [x] その他
272
114
 
273
115
  ##### 上記の詳細・結果
274
- サーバーサイドでセキュリティ対策となるコードを書いていたのですが、1つ目の CSRF 攻撃対してワンタイムトークンを使う必要が出てきたため、現在考えているデザインの新規登録画面から認証コードとユーザーネーム直接メールアドレスに送る方法では、セッションが使えず危険ではないかと感じした
116
+ 今後サーバーサイドでセキュリティ対策となるコードを書いていく際確認画面を設けない場合にメールアドレスに直接信する方法では攻撃を防ぎきれないのではないかと心配しており
275
117
 
276
118
  ### 補足
277
119
  ※ 参考サイト
278
120
  https://html-coding.co.jp/knowhow/security/csrf/
279
121
 
280
- https://www.spiral-platform.co.jp/article/form/16286/
122
+ https://note.com/kohki/n/na9b4bddfa717

2

誤字

2025/04/28 07:26

投稿

homepage-site
homepage-site

スコア70

test CHANGED
File without changes
test CHANGED
@@ -276,3 +276,5 @@
276
276
  ### 補足
277
277
  ※ 参考サイト
278
278
  https://html-coding.co.jp/knowhow/security/csrf/
279
+
280
+ https://www.spiral-platform.co.jp/article/form/16286/

1

誤字

2025/04/28 07:25

投稿

homepage-site
homepage-site

スコア70

test CHANGED
File without changes
test CHANGED
@@ -131,13 +131,6 @@
131
131
  line-height: 2em;
132
132
  }
133
133
 
134
- /* 入力エラーがあった時のスタイル(エラーがあった時は枠の色は分かりずらいので変更せずエラー文のみ表示させる)
135
- .input-error {
136
- border: 1px solid #e52d77;
137
- border-radius: 3px;
138
- background-color: #FCC;
139
- } */
140
-
141
134
  /* クリック時に枠の色を変更 */
142
135
  ○○○:hover {
143
136
  border: 2px solid #000;