がるの健忘録

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

複数ドメインでのセッション管理のポイント

ワードとしては「複数ドメイン間でのセッションの共有」とか「サブドメイン間でセッションの共有」とか「別ドメインでログイン(認可)情報を共有」とかそんな感じになりますかね。
ケースとしては比較的レアかと思うのですが。

今回の場合
・「複数のゲーム」をひとまとめにしたサイトを作りたい
・各ゲームは個々に実装。ディレクトリじゃなくてドメインで切り分ける想定
・ログインだけ「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に以下を用意しました。

hoge/index.php
foo/index.php

<?php  // hoge/index.php, foo/index.php
// 設定確認用
echo 'ok';

hoge/read.php
foo/read.php

<?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';


hoge/write.php

<?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に書きます)」とか。

とりあえず「できるといいなぁできないと気合いで自力実装だなぁ」と思っているところが割とさくっと解決したので、めでたいの思いを込めて一筆。