Laravel7 でマルチ認証

2020/03/24

Laravel 7 で認証ページを作成してみます。

※Laravel7 の認証ページ

https://readouble.com/laravel/7.x/ja/authentication.html

プロジェクト作成


$ composer create-project laravel/laravel laravel-auth --prefer-dist
$ cd laravel-auth
$ chmod -R 777 storage
$ chmod -R 777 bootstrap/cache

この時点で、 config/auth.php などが作成されています。

  • config/auth.php
  • app/User.php
  • app/Http/Middleware/Authenticate.php
  • database/migrations/xxxx_create_users_table.php
  • database/migrations/xxxx_create_password_resets_table.php
  • database/factories/UserFactory.php

User モデル

デフォルトで app/User.php が作成されています。


namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;
    protected $fillable = [
        'name', 'email', 'password',
    ];
    protected $hidden = [
        'password', 'remember_token',
    ];
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

今回は、App/Models/User.php にパスを変更しておきます。
(namespace など修正が必要)

Admin モデル作成

マルチ認証用に、管理者(Admin)モデルを作成してみます。

Models/Admin.php を作成します。


$ php artisan make:model Models/Admin

Admin マイグレートファイル作成

databases/ に Admin用のマイグレーションファイルを作成します。


$ php artisan make:migration create_admins_table

モデル&マイグレートファイルを同時に作成

上記のモデルとマイグレーションファイルを同時に作成することもできます。

Models/Admin.php を作成します。


$ php artisan make:model Models/Admin -m

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
 
class CreateAdminsTable extends Migration
{
    public function up()
    {
        if (Schema::hasTable('admins')) return;
        Schema::create('admins', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
            $table->string('email');
            $table->string('name');
            $table->string('password');
            $table->string('remember_token')->nullable();
        });
    }
    public function down()
    {
        Schema::dropIfExists('admins');
    }
}

Guard の設定

Guard は Auth認証用のドライバークラスで、config/auth.php に設定をします。


    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
      'admin' => [
         'driver' => 'session',
         'provider' => 'admins',
      ],
    ],

Guard を設定することにより、Controllerなどに記載するミドルウェアでの認証が可能となります。


$this->middleware('auth:admin');

config/auth.php の設定

config/auth.php ファイルに Eloquent の App\Models\User クラスを設定します。
※User.php の namespace は App\Models\ に変更


    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],
       'admins' => [
        'driver' => 'eloquent',
        'model' => App\Models\Admin::class,
      ],
    ],

artisan で auth を作成する

make:auth 廃止

Laravel6 から 以下のコマンドは廃止されました。


$ php artisan make:auth

laravel/ui を利用

代わりに、「laravel/ui」でログイン画面を作成するようになりました。

更に、リリースノートには、2.0 を指定するように記載されています。


$ composer require laravel/ui "^2.0"
$ php artisan ui vue --auth

vue の部分は bootstrap などの設定もできます。

認証用ファイル

  • resources/views/auth
  • App/Http/Controllers/Auth

が作成されているので、管理者用にコピーしておくと良いでしょう。

  • resources/views/admin/auth
  • App/Http/Controllers/Admin/Auth

データベース作成

PostgreSQL


$ createdb sample_auth

MySQL


# mysql -u root
mysql > create database sample_auth;

.env

各種DBの設定を合わせる


DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=sample
DB_USERNAME=postgres
DB_PASSWORD=secret

DBマイグレート

DB設定が一通り完了したら、マイグレートしてみます。


$ php artisan migrate

テーブルが作成したことを確認したら、サンプルデータを作成してみます。

Seeder 作成

サンプルデータを作成する場合、artisan に seeder コマンドにも用意されています。

ユーザ、管理者の Seeder を作成すると「database/seeds/」にファイルが書き出されます。


$ php artisan make:seeder UsersTableSeeder
$ php artisan make:seeder AdminsTableSeeder

UsersTableSeeder.php


    public function run()
    {
        DB::table('users')->insert([
            'name' => Str::random(10),
            'email' => Str::random(10).'@gmail.com',
            'password' => Hash::make('password'),
        ]);
    }

AdminsTableSeeder.php


    public function run()
    {
        DB::table('admins')->insert([
                'email' => 'xxxx@xxxx.com',
                'name' => 'Admin',
                'password' => Hash::make('password')
            ]
        );
    }

DatabaseSeeder.php

Seeder ファイルが作成されたら、「database/seeds/DatabaseSeeder.php」に seeder を実行できるよう設定します。


public function run()
{
     $this->call(UsersTableSeeder::class);
     $this->call(AdminsTableSeeder::class);
}

設定したら、artisan コマンドで Seeder を実行します。


$ php artisan db:seed

実際に、テーブルにデータが作成されているか確認してみましょう。

Factory

ここでは割愛しますが、Factory の faker を利用する方法で seeder を実行できます。
Factory ファイルは以下のコマンドで作成できます。


$ php artisan make:factory UserFactory

コントローラー作成

各種コントローラーを作成します。

管理者ホーム

App/Http/Controllers/Admin/ にコントローラーを作成します。


$ php artisan make:controller Admin/HomeController

Admin/HomeController.php

ファイルを作成したら、index の実装と、コンストラクタに認証用のミドルウェアを記述(Guard で設定したパラメータ)をします。
以下の例は、管理者の認証制御となります。


    public function __construct()
    {
        $this->middleware('auth:admin');
    }

    public function index(Request $request)
    {
        return view('admin.index');
    }

ただコントローラが増えてくると、コンストラクタに毎度記述するのも面倒なので、Route のグループ設定で一括管理すると良いでしょう。
(認証用の親コントローラを継承する方法もありますが)

Route の設定

認証が必要・不要のページを考えて、グループ化した Route を設定します。

認証が不要のページ

ログイン、ログアウト、登録ページなどの認証不要のページのルートを作成します。
管理者URIは、admin で統一したいので「admin」プリフィックスを利用しています。

routes/web.php


Route::group(['prefix' => 'admin'], function () {
    Route::get('login', 'Admin\Auth\LoginController@index')->name('admin.login');
    Route::post('login', 'Admin\Auth\LoginController@login')->name('admin.login');
    Route::get('logout', 'Admin\Auth\LoginController@logout')->name('admin.logout');
    Route::post('logout', 'Admin\Auth\LoginController@logout')->name('admin.logout');
});

認証が必要のページ

認証が必要なページのルートを設定します。
ルートグループのパラメータに、ミドルウェアの Guard 設定します。


Route::group(['prefix' => 'admin/topic', 'middleware' => 'auth:admin'], function() {
    Route::get('/', 'Admin\HomeController@index')->name('admin.index');
});