概要
異なるサイト間でCookieとSessionを共有してログイン状態を保持する手順を記載します。
片方のサイトでログインすればもう片方もログイン状態になり、片方でログアウトすればもう片方もログアウトするような感じです。
Laravelで以下の条件を満たしていれば、基本的に設定ファイルを編集するだけでできます。
- サイト間で認証方式が同じ
- サイト間でドメインが同じ
- サイト間で同じデータベースを使用している
今回は、Laravelでデフォルトの認証方式である$ php artisan make:auth
を両方のプロジェクトで実行したとして話を進めます。
独自の認証だったり他のライブラリ等を利用した場合は、設定に関する変更箇所を適宜見つける必要があります。
Cookie/Sessionとは
ステートレス(状態を持たない)であるHTTP通信において、ログイン状態などの状態を保持しておきたいときにCookieとSessionを用います。
Cookieはクライアント側で持つ情報、Sessionはサーバー側で持つ情報です。
これらの情報は連想配列のように取得することが可能です。
環境
Laravel 5.5.45
Homestead 8.2.0
Vagrant 2.2.4
VirtualBox 7.2.1
手順
Cookieをサブドメイン間で共有する
1.認証ドライバの設定
ガードにsessionを指定します。
$ php artisan make:auth
のコマンドで作成した認証方法であれば、あらかじめ設定されているため変更不要ですが、内容を確認してみます。
**ガード(Guard)**とは、Authの認証に利用しているドライバークラスで、各リクエストごとにどのようにユーザーを認証するかを定義します。
各プロジェクトでconfig/auth.php
を開き、webのガードが認証ドライバとしてsessionを指定していることを確認します。
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
また、デフォルトでwebのガードが使用されていることを確認します。
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
2.APP_URLの設定
.env
ファイルのAPP_URLを設定します。
各プロジェクトで、正しいURLを設定してください。
- APP_URL=http://localhost
+ APP_URL=http://shared-session.example.test
2.ドメインの設定
Cookieのドメインの設定をします。
ドメインを指定した場合、Cookieはそのドメイン自体だけでなく、サブドメインに対しても送信されます。
Cookieの仕様で、.comや.jpといったトップレベルドメインに対してはdomain属性は設定しても無効になります。
また、ブラウザによっては.co.jpなど一般的なドメインも無効になる場合があります。
各プロジェクトの.env
ファイルにSESSION_DOMAINを追加し、サイトで使用しているドメインを指定します。
SESSION_DRIVER=file
SESSION_LIFETIME=120
+ SESSION_DOMAIN=.example.test
この定数はconfig/session.php
で読み込まれています。
.env
ファイルにSESSION_DOMAINが存在しない場合にnullを返しています。
'domain' => env('SESSION_DOMAIN', null),
3.Cookie名の設定
Cookie名を指定します。
各プロジェクトの.env
ファイルにSESSION_COOKIEを追加し、任意のCookie名を指定します。
SESSION_DRIVER=file
SESSION_LIFETIME=120
+ SESSION_COOKIE=shared_cookie
もしくは、各プロジェクトの.env
ファイルのAPP_NAMEを同じにします。
config/session.php
で、SESSION_COOKIEがない場合にAPP_NAMEを使用するよう指定しているためです。
APP_NAME=Laravel
'cookie' => env(
'SESSION_COOKIE',
str_slug(env('APP_NAME', 'laravel'), '_').'_session'
),
4.Cookieを復号するためのキーの設定
各プロジェクトの.env
ファイルでAPP_KEYを同じにします。
Cookieに含まれてるセッションIDは暗号化されているため、同一キーでないと復号できないためです。
片方のをコピーして、もう片方のプロジェクトへ貼り付けます。
+ APP_KEY=base64:+UeQnKa......=
5.確認
Cookieがサブドメイン間で共有されていることを確認していきます。
サーバーを再起動し、両方のサイトでログインします。
ブラウザがChromeの場合、 右上のメニューアイコン > 設定 > 詳細設定 > コンテンツの設定 > Cookie > すべての Cookie とサイトデータを表示 を開きます。
参考:Chromeでcookieを確認する方法: 小粋空間
検索バーで「example.test」を検索します。
Cookieがサブドメインごとではなく、指定したドメインに対して作成されています。
クリックすると、SESSION_COOKIEで指定したCookie名になっています。
参考
Sessionをデータベースで共有する
1.Sessionの保存先を設定
Sessionの保存先をデータベースに変更します。
各プロジェクトの.env
ファイルでSESSION_DRIVERをfileからdatabaseに変更します。
- SESSION_DRIVER=file
+ SESSION_DRIVER=database
この定数はconfig/session.php
で読み込まれています。
'driver' => env('SESSION_DRIVER', 'file'),
2.Sessionのテーブルを作成
以下のコマンドでSession用のマイグレーションファイルを作成し、実行してSessionテーブルを作成します。
この操作はどちらか片方のプロジェクトでOKです。
$ php artisan session:table
$ php artisan migrate
3.確認
これでSessionの共有は完了です。
片方でサイトでログインしてみて、もう片方のサイトでリロードするとログイン状態になれば成功です。
また、データベースでSessionテーブルへアクセスしてみてセッションのデータが作成されているか確認してみてください。
$ mysql -u root -p
Enter password:
mysql> show databases;
mysql> use <table名>;
mysql> show tables;
mysql> select * from sessions;
参考
補足
うまく行かない場合
以下の方法等を試してください。
- 設定を片方のプロジェクトのみしていないか確認する
-
storage/framework/sessions
フォルダ内の不要なセッションファイルを消してみる - ブラウザのCookie情報を消してみる
(右上のメニューアイコン > 設定 > 詳細設定 >閲覧履歴データを削除する > Cookieとキャッシュの項目をチェックして「データを削除」をクリック) - サーバーを再起動してみる
(Homesteadを使用してる場合は$ vagrant reload —provision
を実行)
セキュリティについて
CookieとSessionを共有することに関してのセキュリティについて考えます。
Cookieに関しては、domainを指定することによってCookieが送信される範囲が広がるため、挙動を理解しておく必要があります。
CookieのDomain属性は 指定しない が一番安全 | 徳丸浩の日記
Cookie - サブドメイン間のCookieの共有|teratail
また、CookieとSessionを共有することによって片方の情報が漏洩すること=もう片方も漏洩することになるので、漏洩した場合に影響範囲が広くなります。
複数のデータベースを使用している場合
以下が参考になります。
ドメインが全く異なる場合
**シングルサインオン(SSO)**を使用すると実現できると思います。
最後に
記事に間違いや不明な点があれば遠慮なくご指摘ください。