PHPセッションの設定確認

Oauthのstate用にセッションIDをハッシュ化して開発している時に本番環境でうまく動かなかったので、一つずつ原因を紐解いていったときの覚書。

環境: CentOS Stream 8, nginx 1.20.2, PHP 7.4.19, WordPress 5.9.2

Android上のChromeで動作確認している。


PHPセッション設定

まずはPHPのセッション関連設定を確認する。

セッションIDの置き場所の確認
# less /etc/php-fpm.d/www.conf

php_value[session.save_handler] = files
php_value[session.save_path]    = /var/lib/php/session

セッションのタイムアウト時間設定の確認
# php -i | grep session

session.cookie_lifetime => 0 => 0
session.gc_maxlifetime => 1440 => 1440
session.name => PHPSESSID => PHPSESSID

cookie_lifetime=0の場合はブラウザが閉じるまでセッションを維持する。
gc_maxlifetime=1440は秒数。24分経過するとガベージコレクションで(一定確率で)消去される。

念のためphpinfo()をどこかに設置して、php-fpm経由のphpinfo()を表示して確認する。


セッションID生成の動作確認

PHPセッションの基本的な動作は公式サイトを参考に。

session_start()したときに生成したセッションIDを確認する。

ChromeブラウザのDeveloper Toolsの「Network→(リクエストしたパス)→ Cookie」を見る。session_start()するパスではPHPSESSIDが生成されているはず。

Name: PHPSESSID
Value: r4g0chpal344nb5lqb1oq4s3l9

このセッションIDがsession.save_pathにあるか確認
# cd /var/lib/php/session
# ll sess_r4g0chpal344nb5lqb1oq4s3l9

PHPで$_SESSIONに書き込むと、このファイルに書き込まれる。
# cat sess_r4g0chpal344nb5lqb1oq4s3l9

WordPressはPHPセッションを使わないので、開発環境ではphpMyAdminが生成したセッションIDがほとんど。
中身を見るとPMA_tokenと記載されている。
# cat sess_5sjtd9kh8qf76bne6e66146e9r

試しに全部のセッションIDを削除してみる。
(PHPセッションを利用しているシステムはこれをすると接続中のクライアントに予期せぬ不具合が発生するので注意)
# rm -f sess_*

ブラウザでsession_start()するパスへアクセスすると同じセッションIDが生成された。
# ls

今度はDeveloper ToolsでClear browser cookiesをしてみる。
そしてsession_start()するパスへアクセスすると別のセッションIDがResponse Cookieとして生成された。

以後はRequest Cookieに生成されたセッションIDが含まれている。


つまりsession_start()する際にRequest Cookieで値を渡すと同じセッションIDで生成し、値がない場合は新しいセッションIDでResponse Cookieする。

Ajax通信でもCookieに書き込みを行い、次回のリクエストからRequest CookieにPHPSESSIDが入っている。


リダイレクトする前に$_SESSIONへ書き込む場合はsession_write_close()する。


セッションIDを使わない方法

Oauthからcallbackで戻ってきた直後はセッションを使えないということが分かったので、WordPressのTransientsを使って一時保存するようにした。
参考: Transients | Common APIs Handbook | WordPress Developer Resources


あと嵌ったのはWordPress内部でunset($_GET['error'])されて、oauth画面でキャンセルされたときの処理がうまく動かなかったので混乱した。


【関連記事】