PHP のセッションが消えちゃう時にチェックすること
ドットインストールのプログラムが動かない
ユーザ管理を行うプログラムの解説ということで、ドットインストールの「ユーザー管理をするWebサービスを作ろう (全19回)」を観ながらほぼ同じプログラムを MAMP で構築したローカル環境で動かしてみたのですが動きません。
ユーザー管理をするWebサービスを作ろう (全19回) – プログラミングならドットインストール
ソースにデバッグプリントを入れたりしながら調べていくと、
1 2 3 4 5 6 7 8 |
function checkToken() { if (empty($_SESSION['token']) || ($_SESSION['token'] != $_POST['token'])) { echo "不正なPOSTが行われました!"; echo $_SESSION['token']; echo $_POST['token']; exit; } } |
2行目の if 文で $_SESSION[‘token’] が消えてしまっていることが原因だとわかった。$_POST[‘token’] にはきちんとトークンが入っていてこの値は POST 直前に $_SESSION[‘token’] からコピーしたものである。つまり、両方同じ値が入っていて欲しいのだけどなぜか消えてしまう。値のコピーからここまでの間にはページの遷移しかないので、そこがアヤシイ。
困ったときのググレカス
困ったので、自分自身にググレカスと言い聞かせてググりました。が、なかなか解決しない。php.ini の設定を見なおしたり、ローカル環境ではなくサーバ環境でも試してみたけど結果は同じ。
人様の環境と自分の環境が違うのかもしれないけれど、なぜドットインストールの動画ではきちんと動いているのだろう? PHP のバージョンは確かにちょっと違う。うーむ。
で、結局 stackoverflow サイトを見たら同じような質問が載っていて、解決策を答えている人がいました。よし、上から順にやっていこうと思ったら最初の1つ目がビンゴ! あらラッキー。でも、ドットインストールのレクチャー動画ではなぜ動いているのかが未だによくわかりません。
PHP session lost after redirect – Stack Overflow
ようは、session_start() を呼ぶのは <?php の直後じゃなくちゃならず、空白や余計な改行もご法度とのこと。
ドットインストールの index.php, login.php, signup.php の sessionstart 部分を
1 2 3 4 5 6 |
<?php require_once('config.php'); require_once('functions.php'); session_start(); |
から
1 2 3 4 5 |
<?php session_start(); require_once('config.php'); require_once('functions.php'); |
に変更したらあっさり動いてしまいました。違いは session_start() を <?php 直下に持ってきただけ。
session で気をつけるべき点
前述の stackoverflow に書かれていた気をつけるべき点を日本語で要点だけまとめておきます。
- sessin_start() は<?php の直後になくてはならない。空白やタブもあってはならない。
- header リダイレクト後のスクリプト終了は exit(); で行うべし。session_write_close(); などもあるけど自分は exit(); で動いている。
- ブラウザの cookie が使用可能になっていること
- php.ini の register_globals が off になっていること。phpinfo() を呼んでも設定を確認できる。
- session を明示的に消したり空白にしていないこと。
- $_SESSION グローバル変数をどこかで上書きしていないこと
- リダイレクト先が同じドメインであること。ドメインが異なるとセッションは引き継がれない。www.aaa.com から aaa.com へのリダイレクトはセッションが引き継がれない。
- ファイルの拡張子が .php であること。
とのことでした。
https://qiita.com/ssmxgo/items/216ee3841a88ff01f6ef
もし、情報に誤りがあるならば、修正してください。
修正しないと犠牲者が出続けます