質問編集履歴

1

質問投稿の背景について追記

2022/10/09 03:12

投稿

hoshi_no_senshi
hoshi_no_senshi

スコア48

test CHANGED
File without changes
test CHANGED
@@ -24,3 +24,107 @@
24
24
  「想定しているページからの遷移しか許可しない」という実装をする上で何が必要なのか。
25
25
  アドバイス等いただけますと幸いです。よろしくお願いいたします!
26
26
 
27
+ 2022-10-09 お昼 追記
28
+ ---
29
+ ログイン画面(login.php)でユーザ名とパスワードを入力
30
+
31
+ a.phpへ遷移し、DBからデータを取得し、セッション変数に入れてb.phpで扱えるようにする
32
+
33
+ b.phpへ遷移し、取得したデータを表示
34
+
35
+ という一連の流れを実装しようとしました。3つのファイルのソースは下記のものです!
36
+ ```login.php
37
+ <?php
38
+ $randomBytesDigit = 32;
39
+ $csrfToken = bin2hex(random_bytes($randomBytesDigit));
40
+
41
+ session_start();
42
+ $_SESSION['csrf_token'] = $csrfToken;
43
+ ?>
44
+ <!DOCTYPE html>
45
+ <html lang="ja">
46
+ <head>
47
+ <!-- 略 -->
48
+ </head>
49
+ <body>
50
+ <form action="./a.php" method="POST">
51
+ ユーザ名:<input type="text" name="username"><br>
52
+ パスワード:<input type="password" name="password"><br>
53
+ <input type="hidden" name="csrf_token" value="<?=$csrfToken?>">
54
+ 送信:<input type="submit">
55
+ </form>
56
+ </body>
57
+ </html>
58
+ ```
59
+ ```a.php
60
+ <?php
61
+ session_start();
62
+ if(array_key_exists("csrf_token", $_SESSION)){
63
+ if($_SESSION['csrf_token'] !== $_POST['csrf_token']){
64
+ //トークンが一致しないためlogin.php以外から遷移してきたものと断定し、ログイン画面へ強制遷移
65
+ header("Location: ./login.php");
66
+ exit;
67
+ }
68
+ }else{
69
+ //セッション変数にCSRFトークンが入っていなかった時点で不正リクエストと断定し、ログイン画面へ強制遷移
70
+ header("Location: ./login.php");
71
+ exit;
72
+ }
73
+
74
+ define("USER", "user");
75
+ define("PASSWORD", "pass");
76
+
77
+ if(isset($_POST['username']) && isset($_POST['password'])){
78
+ if($_POST['username'] !== USER || $_POST['password'] !== PASSWORD){
79
+ echo 'ユーザ名かパスワードが、ちがいます!<br>';
80
+ echo '<a href="./login.php">ログイン画面</a>';
81
+ exit;
82
+ }
83
+ }
84
+
85
+ $dsn = 'mysql:host=test;dbname=test_db;charset=utf8';
86
+ $db_user = 'root';
87
+ $db_pass = 'pass';
88
+ $driver_options = [
89
+ //オプション使用の際は追記
90
+ ];
91
+
92
+ try {
93
+ $pdo = new PDO($dsn, $db_user, $db_pass, $driver_options);
94
+ } catch (PDOException $e) {
95
+ exit('DB接続失敗:' . $e->getMessage());
96
+ }
97
+
98
+ $sql = 'SELECT id FROM test'; //「test」というテーブルからid一覧を取得
99
+ $stmt = $pdo->query($sql);
100
+
101
+ if(!$stmt){
102
+ echo 'DBからのデータ取得にしっぱいしました・・・';
103
+ exit;
104
+ }
105
+
106
+ $_SESSION['data'] = $stmt->fetchAll(PDO::FETCH_ASSOC); //「test」テーブルから取得したデータをb.phpへ渡すためセッション変数へ格納
107
+ header("Location: ./b.php");
108
+ ```
109
+ ```b.php
110
+ <?php
111
+ session_start();
112
+
113
+ //DBから取得されているはずのデータを受け取っていない場合、ログイン画面へ戻る
114
+ if(!isset($_SESSION['data'])){
115
+ header('Location: ./login.php');
116
+ exit;
117
+ }else{
118
+ echo '<pre>';
119
+ var_dump($_SESSION['data']);
120
+ echo '</pre>';
121
+ }
122
+ echo "a.phpで取得したDBのデータが正常に表示されました!";
123
+ ```
124
+ 気になったのはb.phpについてです。「$_SESSION['data']」には、a.phpにてDBから取得したデータが入っているはずなので、その内容を画面に表示する。そのような役割をb.phpは担っています。
125
+ そのため、もし「$_SESSION['data']」にデータがはいっていないということがもしあれば、そのときは異常事態なので、とりあえずログイン画面に強制遷移するようにしています。
126
+ しかし、a.php以外のページでもしも「$_SESSION['data']」にデータを入れた状態でb.phpに遷移された場合、意図せぬ形で画面表示が行われると考え、当質問のタイトルに「a.phpからb.phpに遷移したとき、a.phpから遷移したことを保証する手段」という内容を設定しました。
127
+ ただ、もし外部ページから「$_SESSION['data']」が渡されてそれがb.phpで表示されたとしても、特に実害が発生することはなさそう、という思いもあります!
128
+ したがいまして、そのような特例まではめんどうをみなくてもよいかもしれない、とも考えております。
129
+
130
+ 上記内容を踏まえご意見頂戴できますと幸いです、よろしくお願いいたします!