複数ドメインでのセッション管理のポイント
ワードとしては「複数ドメイン間でのセッションの共有」とか「サブドメイン間でセッションの共有」とか「別ドメインでログイン(認可)情報を共有」とかそんな感じになりますかね。
ケースとしては比較的レアかと思うのですが。
今回の場合
・「複数のゲーム」をひとまとめにしたサイトを作りたい
・各ゲームは個々に実装。ディレクトリじゃなくてドメインで切り分ける想定
・ログインだけ「1カ所に集約」して、ユーザ登録は1回で片付けられるようにしたい
って感じです(プチ宣伝込み)。
あんまり「よくあるニーズ」ではなさそうなんですが。
まぁその分「必要な人には必要だろう」って建前と、ぶっちゃけ「書いておかないと自分が忘れるがな」っていうこのblog本来の目的のために、書いておきます(笑
まず事前準備。
# とりあえず基底のディレクトリ作る mkdir session_test; cd $_ # 2つのドメイン用のディレクトリをそれぞれ作る mkdir hoge mkdir foo # DNS設定(略 # nginx設定(略
nginxの設定の一部だけ書いておくとこんな感じです。
server { listen 80; server_name hoge.example.com; root /home/example/session_test/hoge/; (略) }
server { listen 80; server_name foo.example.com; root /home/example/session_test/foo/; (略) }
この辺はいわゆるインフラ系のお仕事。
ドメインは
hoge.example.com
foo.example.com
の2つを用意しました。
実際には
www.example.com
ゲーム1.example.com
ゲーム2.example.com
って感じのを用意して、wwwのほうに「ユーザ登録、ログイン機能」「ゲームの一覧」あたりを実装、各ゲームはゲーム1とかゲーム2とかのドメインに実装予定です。
(その時用の共通化についてもいろいろ考えているので、ある程度実装したら今度、記事にする予定です)。
用意したコードは以下の通り。
まず session_test に、共通の「セッション用のコード」を用意しています。
<?php // common.php declare(strict_types=1); // ob_start(); // ざっくりセッション設定 session_set_cookie_params([ 'lifetime' => 0, 'samesite' => 'Strict', // 'secure' => true, // テスト環境なのでhttpsになってないからコメントアウト 'httponly' => true, 'domain' => 'example.com', // ここは、テストによって有効にしたりコメントアウトしたり ]); // ini_set('session.use_strict_mode', 1); // セッション開始 session_start();
次に、hogeとfooに以下を用意しました。
<?php // hoge/index.php, foo/index.php // 設定確認用 echo 'ok';
<?php // hoge/read.php, foo/read.php declare(strict_types=1); require __DIR__ . '/../common.php'; // セッション情報の表示 var_dump($_SESSION); var_dump(session_id());
hoge/regenerate.php
foo/regenerate.php
<?php // hoge/regenerate.php, foo/regenerate.php declare(strict_types=1); require __DIR__ . '/../common.php'; // セッションID差し替え session_regenerate_id(true); echo 'ok';
<?php // hoge/write.php declare(strict_types=1); require __DIR__ . '/../common.php'; // セッションへの書き込み $_SESSION['hoge'] = 'hoge value'; // echo 'ok';
foo/write.php
<?php // foo/write.php declare(strict_types=1); require __DIR__ . '/../common.php'; // セッションへの書き込み $_SESSION['foo'] = 'foo value'; // echo 'ok';
準備完了。
まずは
'domain' => 'gjmj.net', // ここは、テストによって有効にしたりコメントアウトしたり
をコメントアウトした状態で、「だよね~」の確認。
http://hoge.example.com/read.php
array(0) { }
string(32) "19c0589b071e4d2d5e995028cb9081aa"
http://foo.example.com/read.php
array(0) { }
string(32) "0187f6525a7d24e03b662e564471747f"
http://hoge.example.com/write.php
http://foo.example.com/write.php
http://hoge.example.com/read.php
array(1) { ["hoge"]=> string(10) "hoge value" }
string(32) "19c0589b071e4d2d5e995028cb9081aa"
http://foo.example.com/read.php
array(1) { ["foo"]=> string(9) "foo value" }
string(32) "0187f6525a7d24e03b662e564471747f"
当然ではありますが「違うドメイン」なので、違うセッションIDだし違う情報を書いてるし読んでるから、交わることなし。
次。今回の眼目。domainの所を有効にして実験。
http://hoge.example.com/read.php
array(0) { }
string(32) "8b5f581950014979cb679dee1c07d449"
http://foo.example.com/read.php
array(0) { }
string(32) "8b5f581950014979cb679dee1c07d449"
http://hoge.example.com/write.php
http://foo.example.com/write.php
http://hoge.example.com/read.php
array(2) { ["hoge"]=> string(10) "hoge value" ["foo"]=> string(9) "foo value" }
string(32) "8b5f581950014979cb679dee1c07d449"
http://foo.example.com/read.php
array(2) { ["hoge"]=> string(10) "hoge value" ["foo"]=> string(9) "foo value" }
string(32) "8b5f581950014979cb679dee1c07d449"
http://hoge.example.com/regenerate.php
http://foo.example.com/regenerate.php
http://hoge.example.com/read.php
array(2) { ["hoge"]=> string(10) "hoge value" ["foo"]=> string(9) "foo value" }
string(32) "f4a57c3d4dc2e0fe4f4fb4b167d4dcd2"
http://foo.example.com/read.php
array(2) { ["hoge"]=> string(10) "hoge value" ["foo"]=> string(9) "foo value" }
string(32) "f4a57c3d4dc2e0fe4f4fb4b167d4dcd2"
予想通り。
session_regenerate_id() も含めて、ちゃんと意図的に動いてくれる感じ。
まぁこれだと「ゲーム本体の情報」を下手にセッションにぶち込んだ時に割と死ねるんだけど。
その辺は最悪「(PHPのセッションは)認可と共通情報専用」にして「別途、個別ゲーム情報用のセッション」は組み直してもいいしなぁ……あとは「セッション名のスイッチング(この辺も、面白そうだったら今度blogに書きます)」とか。
とりあえず「できるといいなぁできないと気合いで自力実装だなぁ」と思っているところが割とさくっと解決したので、めでたいの思いを込めて一筆。