💬

Laravelのどのバージョンでもユーザーの強制ログアウトを実装する方法

2021/04/30に公開

今回は強制的にユーザーをログアウトする方法について解説していきたいと思います。

Laravel5.6から logoutOtherDevices というのが追加されて、簡単に指定のユーザーを強制的にログアウトすることができるそうです(試していない)

少し引用すると

Note: logoutOtherDevicesメソッドが起動すると、ユーザーの他のセッションは全て無効になります。つまり、以前に認証済みの全てのガードが、「ログアウト」されます。

だそうです。

↓5.6の記事ですが。
Laravel 5.6 認証

ただ僕が強制ログアウトを実装したかったのはLaravel5.5のプロジェクトだったこともあり、(logoutOtherDevicesにパスワードを渡す意味が分からなかったこともあり)バージョンに依存しない強制ログアウトの方法を考えました。

バージョンに依存しないユーザー強制ログアウトの方法

簡潔にやり方を説明するとこんな感じです。↓

  1. usersテーブルに強制ログアウトフラグを追加する。(例えばis_force_logoutというカラム名にしてみる。初期値は0)
  2. 強制ログアウトしたいユーザーのis_force_logoutを1にする。
  3. ミドルウェアでリクエストをキャッチして、is_force_logoutが1だったらログアウト処理をしてログイン画面にリダイレクトする。is_force_logoutを0に戻す。

1. usersテーブルに強制ログアウトフラグを追加する

マイグレーションファイルを作ります。

$ php artisan make:migration add_is_force_logout_to_users_table --table=users

生成されたマイグレーションファイルの中身を編集します。

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddIsForceLogoutToUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->integer('is_force_logout')->default(0);
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('is_force_logout');
        });
    }
}

2. 強制ログアウトしたいユーザーのis_force_logoutを1にする

Controllerの処理は、is_force_logoutに1をいれるだけです。

public function forceLogout(User $user)
{
    $user->is_force_logout = 1;
    $user->save();
}

3. ミドルウェアでis_force_logoutの中身を判定する

ミドルウェアを定義していきます。

php artisan make:middleware checkForceLogout

ミドルウェアの中身はこんな感じです。

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class CheckForceLogout
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $user = Auth::user();
        if ($user && $user->is_force_logout)) {
            $user->logout();
            $user->is_force_logout = 0;
            $user->save();
            $request->session()->invalidate(); // セッション削除・再生成(もしかしたら不要かも)
            return redirect(route('login'));
        }

        return $next($request);
    }
}

そして、 app/Http/Kernel.php にミドルウェアを登録して、web.phpで適用させると完成です!

終わりに

今回はLaravelのバージョンに依存しない強制ログアウトの方法について説明しました。
もっといい方法があるよー!っていう方はぜひコメントなどで教えて下さい!

Discussion