admin と professor を追加してマルチ認証を実装しよう.
設定ファイルを編集して,admin と professor の項目を追加する.このとき,単数形と複数形の使い方に注意すること.
config/auth.php
- <?php
-
- return [
-
- /*
- |--------------------------------------------------------------------------
- | Authentication Defaults
- |--------------------------------------------------------------------------
- |
- | This option controls the default authentication "guard" and password
- | reset options for your application. You may change these defaults
- | as required, but they're a perfect start for most applications.
- |
- */
-
- 'defaults' => [
- 'guard' => 'user',
- 'passwords' => 'users',
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Authentication Guards
- |--------------------------------------------------------------------------
- |
- | Next, you may define every authentication guard for your application.
- | Of course, a great default configuration has been defined for you
- | here which uses session storage and the Eloquent user provider.
- |
- | All authentication drivers have a user provider. This defines how the
- | users are actually retrieved out of your database or other storage
- | mechanisms used by this application to persist your user's data.
- |
- | Supported: "session", "token"
- |
- */
-
- 'guards' => [
- 'web' => [
- 'driver' => 'session',
- 'provider' => 'users',
- ],
-
- 'api' => [
- 'driver' => 'token',
- 'provider' => 'users',
- ],
-
- 'user' => [
- 'driver' => 'session',
- 'provider' => 'users',
- ],
-
- 'professor' => [
- 'driver' => 'session',
- 'provider' => 'professors',
- ],
-
- 'admin' => [
- 'driver' => 'session',
- 'provider' => 'admins',
- ],
- ],
-
- /*
- |--------------------------------------------------------------------------
- | User Providers
- |--------------------------------------------------------------------------
- |
- | All authentication drivers have a user provider. This defines how the
- | users are actually retrieved out of your database or other storage
- | mechanisms used by this application to persist your user's data.
- |
- | If you have multiple user tables or models you may configure multiple
- | sources which represent each model / table. These sources may then
- | be assigned to any extra authentication guards you have defined.
- |
- | Supported: "database", "eloquent"
- |
- */
-
- 'providers' => [
- 'users' => [
- 'driver' => 'eloquent',
- 'model' => App\User::class,
- ],
- 'professors' => [
- 'driver' => 'eloquent',
- 'model' => App\Professor::class,
- ],
- 'admins' => [
- 'driver' => 'eloquent',
- 'model' => App\Admin::class,
- ],
- // 'users' => [
- // 'driver' => 'database',
- // 'table' => 'users',
- // ],
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Resetting Passwords
- |--------------------------------------------------------------------------
- |
- | You may specify multiple password reset configurations if you have more
- | than one user table or model in the application and you want to have
- | separate password reset settings based on the specific user types.
- |
- | The expire time is the number of minutes that the reset token should be
- | considered valid. This security feature keeps tokens short-lived so
- | they have less time to be guessed. You may change this as needed.
- |
- */
-
- 'passwords' => [
- 'users' => [
- 'provider' => 'users',
- 'table' => 'password_resets',
- 'expire' => 60,
- ],
- 'professors' => [
- 'provider' => 'professors',
- 'table' => 'password_resets',
- 'expire' => 60,
- ],
- 'admins' => [
- 'provider' => 'admins',
- 'table' => 'password_resets',
- 'expire' => 60,
- ],
- ],
-
- ];
admin と professor のログイン画面へのリダイレクト先を変更する.(Laravel 5.7 では app/Http/Middleware/Authenticate.php に記述するようになりました.詳細は後日公開します.)
app/Exceptions/Handler.php
- <?php
-
- namespace App\Exceptions;
-
- use Exception;
- use Illuminate\Auth\AuthenticationException;
- use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
-
- class Handler extends ExceptionHandler
- {
- /**
- * A list of the exception types that should not be reported.
- *
- * @var array
- */
- protected $dontReport = [
- \Illuminate\Auth\AuthenticationException::class,
- \Illuminate\Auth\Access\AuthorizationException::class,
- \Symfony\Component\HttpKernel\Exception\HttpException::class,
- \Illuminate\Database\Eloquent\ModelNotFoundException::class,
- \Illuminate\Session\TokenMismatchException::class,
- \Illuminate\Validation\ValidationException::class,
- ];
-
- /**
- * Report or log an exception.
- *
- * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
- *
- * @param \Exception $exception
- * @return void
- */
- public function report(Exception $exception)
- {
- parent::report($exception);
- }
-
- /**
- * Render an exception into an HTTP response.
- *
- * @param \Illuminate\Http\Request $request
- * @param \Exception $exception
- * @return \Illuminate\Http\Response
- */
- public function render($request, Exception $exception)
- {
- return parent::render($request, $exception);
- }
-
- /**
- * Convert an authentication exception into an unauthenticated response.
- *
- * @param \Illuminate\Http\Request $request
- * @param \Illuminate\Auth\AuthenticationException $exception
- * @return \Illuminate\Http\Response
- */
- protected function unauthenticated($request, AuthenticationException $exception)
- {
- if ($request->expectsJson()) {
- return response()->json(['error' => 'Unauthenticated.'], 401);
- }
- if (in_array('admin', $exception->guards(), true)) {
- return redirect()->guest(route('admin.login'));
- }
- if (in_array('professor', $exception->guards(), true)) {
- return redirect()->guest(route('professor.login'));
- }
-
- return redirect()->guest(route('login'));
- }
- }
artisan コマンドで Admin と Professor モデルを生成する.
[GakuinHana@rin06 laravelUser]$ php artisan make:model Admin ⏎ Model created successfully. [GakuinHana@rin06 laravelUser]$ php artisan make:model Professor ⏎ Model created successfully. [GakuinHana@rin06 laravelUser]$
マイグレーションファイルを生成する.
[GakuinHana@rin06 laravelUser]$ php artisan make:migration create_admins_table --create=admins ⏎ Created Migration: 2018_07_07_152520_create_admins_table [GakuinHana@rin06 laravelUser]$ php artisan make:migration create_professors_table --create=professors ⏎ Created Migration: 2018_07_07_152539_create_professors_table [GakuinHana@rin06 laravelUser]$
生成されたマイグレーションファイルを編集する.
database/migrations/20xx_xx_x_xxxxxx_create_admins_table.php
- <?php
-
- use Illuminate\Support\Facades\Schema;
- use Illuminate\Database\Schema\Blueprint;
- use Illuminate\Database\Migrations\Migration;
-
- class CreateAdminsTable extends Migration
- {
- /**
- * Run the migrations.
- *
- * @return void
- */
- public function up()
- {
- Schema::create('admins', function (Blueprint $table) {
- $table->increments('id');
- $table->string('name');
- $table->string('email')->unique();
- $table->string('login_id')->unique();
- $table->string('password');
- $table->rememberToken();
- $table->timestamps();
- });
- }
-
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::dropIfExists('admins');
- }
- }
database/migrations/20xx_xx_xx_xxxxxx_create_professors_table.php
- <?php
-
- use Illuminate\Support\Facades\Schema;
- use Illuminate\Database\Schema\Blueprint;
- use Illuminate\Database\Migrations\Migration;
-
- class CreateProfessorsTable extends Migration
- {
- /**
- * Run the migrations.
- *
- * @return void
- */
- public function up()
- {
- Schema::create('professors', function (Blueprint $table) {
- $table->increments('id');
- $table->string('name');
- $table->string('email')->unique();
- $table->string('login_id')->unique();
- $table->string('password');
- $table->rememberToken();
- $table->timestamps();
- });
- }
-
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::dropIfExists('professors');
- }
- }
マイグレーションを実行する.
[GakuinHana@rin06 laravelUser]$ php artisan migrate:status ⏎ +------+------------------------------------------------+ | Ran? | Migration | +------+------------------------------------------------+ | Y | 2014_10_12_000000_create_users_table | | Y | 2014_10_12_100000_create_password_resets_table | | Y | 2018_07_01_163318_create_jobs_table | | Y | 2018_07_01_163336_create_failed_jobs_table | | N | 2018_07_07_152520_create_admins_table | | N | 2018_07_07_152539_create_professors_table | +------+------------------------------------------------+ [GakuinHana@rin06 laravelUser]$ php artisan migrate ⏎ Migrating: 2018_07_07_152520_create_admins_table Migrated: 2018_07_07_152520_create_admins_table Migrating: 2018_07_07_152539_create_professors_table Migrated: 2018_07_07_152539_create_professors_table [GakuinHana@rin06 laravelUser]$ php artisan migrate:status ⏎ +------+------------------------------------------------+ | Ran? | Migration | +------+------------------------------------------------+ | Y | 2014_10_12_000000_create_users_table | | Y | 2014_10_12_100000_create_password_resets_table | | Y | 2018_07_01_163318_create_jobs_table | | Y | 2018_07_01_163336_create_failed_jobs_table | | Y | 2018_07_07_152520_create_admins_table | | Y | 2018_07_07_152539_create_professors_table | +------+------------------------------------------------+ [GakuinHana@rin06 laravelUser]$
テスト用のシーダーを生成する.
[GakuinHana@rin06 laravelUser]$ php artisan make:seeder AdminsTableSeeder ⏎ Seeder created successfully. [GakuinHana@rin06 laravelUser]$ php artisan make:seeder ProfessorsTableSeeder ⏎ Seeder created successfully. [GakuinHana@rin06 laravelUser]$
シーダーにテストデータを追加する.
database/seeds/DatabaseSeeder.php
- <?php
-
- use Illuminate\Database\Seeder;
-
- class DatabaseSeeder extends Seeder
- {
- /**
- * Run the database seeds.
- *
- * @return void
- */
- public function run()
- {
- $this->call(UsersTableSeeder::class);
- $this->call(AdminsTableSeeder::class);
- $this->call(ProfessorsTableSeeder::class);
- }
- }
database/seeds/AdminsTableSeeder.php
- <?php
-
- use Illuminate\Database\Seeder;
-
- use App\Admin;
- use Carbon\Carbon;
-
- class AdminsTableSeeder extends Seeder
- {
- /**
- * Run the database seeds.
- *
- * @return void
- */
- public function run()
- {
- DB::table('admins')->delete();
-
- Admin::create([
- 'name' => 'Taro Admin',
- 'email' => 'taro@sample.com',
- 'login_id' => 'taro',
- 'password' => bcrypt('admin'),
- 'created_at' => Carbon::now()
- ]);
-
- Admin::create([
- 'name' => 'Jiro Admin',
- 'email' => 'jiro@sample.com',
- 'login_id' => 'jiro',
- 'password' => bcrypt('admin'),
- 'created_at' => Carbon::now()
- ]);
- }
- }
database/seeds/ProfessorsTableSeeder.php
- <?php
-
- use Illuminate\Database\Seeder;
-
- use App\Professor;
- use Carbon\Carbon;
-
- class ProfessorsTableSeeder extends Seeder
- {
- /**
- * Run the database seeds.
- *
- * @return void
- */
- public function run()
- {
- DB::table('professors')->delete();
-
- Professor::create([
- 'name' => 'Tama',
- 'email' => 'tama@sample.com',
- 'login_id' => 'tama',
- 'password' => bcrypt('professor'),
- 'created_at' => Carbon::now()
- ]);
-
- Professor::create([
- 'name' => 'Pochi',
- 'email' => 'poch@sample.com',
- 'login_id' => 'pochi',
- 'password' => bcrypt('professor'),
- 'created_at' => Carbon::now()
- ]);
- }
- }
シーダーを実行する.まずは dump-autoload を実行しなければエラーになるはず.
[GakuinHana@rin06 laravelUser]$ php ../composer.phar dump-autoload ⏎ Generating optimized autoload files [GakuinHana@rin06 laravelUser]$ php artisan db:seed ⏎ Seeding: UsersTableSeeder Seeding: AdminsTableSeeder Seeding: ProfessorsTableSeeder [GakuinHana@rin06 laravelUser]$
app/Http/Controllers/ 以下に Admin と Professor というフォルダを作成する.その後,artisan コマンドでコントローラを生成する.
[GakuinHana@rin06 laravelUser]$ mkdir app/Http/Controllers/Admin ⏎ [GakuinHana@rin06 laravelUser]$ mkdir app/Http/Controllers/Professor ⏎ [GakuinHana@rin06 laravelUser]$ php artisan make:controller Admin/LoginController ⏎ Controller created successfully. [GakuinHana@rin06 laravelUser]$ php artisan make:controller Admin/HomeController ⏎ Controller created successfully. [GakuinHana@rin06 laravelUser]$ php artisan make:controller Professor/LoginController ⏎ Controller created successfully. [GakuinHana@rin06 laravelUser]$ php artisan make:controller Professor/HomeController ⏎ Controller created successfully. [GakuinHana@rin06 laravelUser]$
それぞれの認証クラスでのルートを定義する.なお,'prefix' => 'admin'
は URL の先頭に admin がつく,すなわち,「login」の URL は「/admin/login」となることを意味している.また,Route::group
の中で middleware を定義しているので,コントローラで明示的に middleware を呼び出さなくてもコントローラですべての処理に認証が要求される(ただし,このあとの例では念の為,コントローラでも middleware を呼び出している).
routes/web.php
- <?php
-
- /*
- |--------------------------------------------------------------------------
- | Web Routes
- |--------------------------------------------------------------------------
- |
- | Here is where you can register web routes for your application. These
- | routes are loaded by the RouteServiceProvider within a group which
- | contains the "web" middleware group. Now create something great!
- |
- */
-
- Route::get('/', function () {
- return view('welcome');
- });
-
- Route::get('/auth/verifyemail/{token}', 'Auth\RegisterController@verify');
-
- Auth::routes();
- Route::get('/resend', 'Auth\RegisterController@showReSendForm')->name('resend');
- Route::post('/resend', 'Auth\RegisterController@reSend');
- Route::get('/password/change', 'Auth\ChangePasswordController@edit');
- Route::patch('/password/change','Auth\ChangePasswordController@update')->name('password.change');
-
- // User ログイン後
- Route::group(['middleware' => 'auth:user'], function() {
- Route::get('/home', 'HomeController@index')->name('home');
- Route::get('/users/{id}', 'UsersController@show');
- });
-
- // Admin 認証不要
- Route::group(['prefix' => 'admin'], function() {
- Route::get('login', 'Admin\LoginController@showLoginForm')->name('admin.login');
- Route::post('login', 'Admin\LoginController@login');
- });
-
- // Admin ログイン後
- Route::group(['prefix' => 'admin', 'middleware' => 'auth:admin'], function() {
- Route::get('home', 'Admin\HomeController@index')->name('admin.home');
- Route::post('logout', 'Admin\LoginController@logout')->name('admin.logout');
- });
-
- // Professor 認証不要
- Route::group(['prefix' => 'professor'], function() {
- Route::get('login', 'Professor\LoginController@showLoginForm')->name('professor.login');
- Route::post('login', 'Professor\LoginController@login');
- });
-
- // Professor ログイン後
- Route::group(['prefix' => 'professor', 'middleware' => 'auth:professor'], function() {
- Route::get('home', 'Professor\HomeController@index')->name('professor.home');
- Route::post('logout', 'Professor\LoginController@logout')->name('professor.logout');
- });
artisan コマンドでルートの定義を確認しておこう.
[GakuinHana@rin06 laravelUser]$ php artisan route:list ⏎ +--------+----------+--------------------------+------------------+------------------------------------------------------------------------+--------------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+----------+--------------------------+------------------+------------------------------------------------------------------------+--------------------+ | | GET|HEAD | / | | Closure | web | | | GET|HEAD | admin/home | admin.home | App\Http\Controllers\Admin\HomeController@index | web,auth:admin | | | POST | admin/login | | App\Http\Controllers\Admin\LoginController@login | web | | | GET|HEAD | admin/login | admin.login | App\Http\Controllers\Admin\LoginController@showLoginForm | web | | | POST | admin/logout | admin.logout | App\Http\Controllers\Admin\LoginController@logout | web,auth:admin | | | GET|HEAD | api/user | | Closure | api,auth:api | | | GET|HEAD | auth/verifyemail/{token} | | App\Http\Controllers\Auth\RegisterController@verify | web,guest | | | GET|HEAD | home | home | App\Http\Controllers\HomeController@index | web,auth:user,auth | | | GET|HEAD | login | login | App\Http\Controllers\Auth\LoginController@showLoginForm | web,guest | | | POST | login | | App\Http\Controllers\Auth\LoginController@login | web,guest | | | POST | logout | logout | App\Http\Controllers\Auth\LoginController@logout | web | | | GET|HEAD | password/change | | App\Http\Controllers\Auth\ChangePasswordController@edit | web,auth | | | PATCH | password/change | password.change | App\Http\Controllers\Auth\ChangePasswordController@update | web,auth | | | POST | password/email | password.email | App\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail | web,guest | | | POST | password/reset | | App\Http\Controllers\Auth\ResetPasswordController@reset | web,guest | | | GET|HEAD | password/reset | password.request | App\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm | web,guest | | | GET|HEAD | password/reset/{token} | password.reset | App\Http\Controllers\Auth\ResetPasswordController@showResetForm | web,guest | | | GET|HEAD | professor/home | professor.home | App\Http\Controllers\Professor\HomeController@index | web,auth:professor | | | GET|HEAD | professor/login | professor.login | App\Http\Controllers\Professor\LoginController@showLoginForm | web | | | POST | professor/login | | App\Http\Controllers\Professor\LoginController@login | web | | | POST | professor/logout | professor.logout | App\Http\Controllers\Professor\LoginController@logout | web,auth:professor | | | GET|HEAD | register | register | App\Http\Controllers\Auth\RegisterController@showRegistrationForm | web,guest | | | POST | register | | App\Http\Controllers\Auth\RegisterController@register | web,guest | | | GET|HEAD | resend | resend | App\Http\Controllers\Auth\RegisterController@showReSendForm | web,guest | | | POST | resend | | App\Http\Controllers\Auth\RegisterController@reSend | web,guest | | | GET|HEAD | users/{id} | | App\Http\Controllers\UsersController@show | web,auth:user,auth | +--------+----------+--------------------------+------------------+------------------------------------------------------------------------+--------------------+ [GakuinHana@rin06 laravelUser]$
生成されたモデルを編集する.(同じフォルダにある User.php をコピーして一部修正しても良い.)
app/Admin.php
- <?php
-
- namespace App;
-
- use Illuminate\Notifications\Notifiable;
- use Illuminate\Foundation\Auth\User as Authenticatable;
-
- class Admin extends Authenticatable
- {
- use Notifiable;
-
- /**
- * The attributes that are mass assignable.
- *
- * @var array
- */
- protected $fillable = [
- 'name', 'email', 'password',
- ];
-
- /**
- * The attributes that should be hidden for arrays.
- *
- * @var array
- */
- protected $hidden = [
- 'password', 'remember_token',
- ];
- }
app/Professor.php
- <?php
-
- namespace App;
-
- use Illuminate\Notifications\Notifiable;
- use Illuminate\Foundation\Auth\User as Authenticatable;
-
- class Professor extends Authenticatable
- {
- use Notifiable;
-
- /**
- * The attributes that are mass assignable.
- *
- * @var array
- */
- protected $fillable = [
- 'name', 'email', 'password',
- ];
-
- /**
- * The attributes that should be hidden for arrays.
- *
- * @var array
- */
- protected $hidden = [
- 'password', 'remember_token',
- ];
- }
ルートに定義した関数をコントローラに設置する.とりあえず雛形だけ.
app/Http/Controllers/Admin/LoginController.php
- <?php
-
- namespace App\Http\Controllers\Admin;
-
- use Illuminate\Foundation\Auth\AuthenticatesUsers; // 追加 (app/Http/Controllers/Auth/LoginController.php からコピーすれば良い)
- use Illuminate\Http\Request;
- use App\Http\Controllers\Controller;
- use Illuminate\Support\Facades\Auth;
-
- class LoginController extends Controller
- {
- /*
- |--------------------------------------------------------------------------
- | Login Controller
- |--------------------------------------------------------------------------
- |
- | This controller handles authenticating users for the application and
- | redirecting them to your home screen. The controller uses a trait
- | to conveniently provide its functionality to your applications.
- |
- */
-
- use AuthenticatesUsers;
-
- /**
- * Where to redirect users after login.
- *
- * @var string
- */
- protected $redirectTo = '/admin/home';
-
- /**
- * Create a new controller instance.
- *
- * @return void
- */
- public function __construct()
- {
- $this->middleware('guest:admin')->except('logout');
- }
-
- public function showLoginForm()
- {
- dd("admin.showLoginForm");
- }
-
- protected function guard()
- {
- return Auth::guard('admin');
- }
-
- public function logout(Request $request)
- {
- $this->guard('admin')->logout();
- $request->session()->invalidate();
- return redirect('/admin/login');
- }
-
- public function username()
- {
- return 'login_id';
- }
- }
app/Http/Controllers/Admin/HomeController.php
- <?php
-
- namespace App\Http\Controllers\Admin;
-
- use Illuminate\Http\Request;
- use App\Http\Controllers\Controller;
-
- class HomeController extends Controller
- {
- /**
- * Create a new controller instance.
- *
- * @return void
- */
- public function __construct()
- {
- $this->middleware('auth:admin');
- }
-
- /**
- * Show the application dashboard.
- *
- * @return \Illuminate\Http\Response
- */
- public function index()
- {
- dd("admin.index");
- }
- }
app/Http/Controllers/Professor/LoginController.php
- <?php
-
- namespace App\Http\Controllers\Professor;
-
- use Illuminate\Foundation\Auth\AuthenticatesUsers; // 追加 (app/Http/Controllers/Auth/LoginController.php からコピーすれば良い)
- use Illuminate\Http\Request;
- use App\Http\Controllers\Controller;
- use Illuminate\Support\Facades\Auth;
-
- class LoginController extends Controller
- {
- /*
- |--------------------------------------------------------------------------
- | Login Controller
- |--------------------------------------------------------------------------
- |
- | This controller handles authenticating users for the application and
- | redirecting them to your home screen. The controller uses a trait
- | to conveniently provide its functionality to your applications.
- |
- */
-
- use AuthenticatesUsers;
-
- /**
- * Where to redirect users after login.
- *
- * @var string
- */
- protected $redirectTo = '/professor/home';
-
- /**
- * Create a new controller instance.
- *
- * @return void
- */
- public function __construct()
- {
- $this->middleware('guest:professor')->except('logout');
- }
-
- public function showLoginForm()
- {
- dd("professor.showLoginForm");
- }
-
- protected function guard()
- {
- return Auth::guard('professor');
- }
-
- public function logout(Request $request)
- {
- Auth::gurad('professor')->logout();
- $request->session()->flush();
- $request->session()->regenerate();
- return redirect('/professor/login');
- }
-
- public function username()
- {
- return 'login_id';
- }
- }
app/Http/Controllers/Professor/HomeController.php
- <?php
-
- namespace App\Http\Controllers\Professor;
-
- use Illuminate\Http\Request;
- use App\Http\Controllers\Controller;
-
- class HomeController extends Controller
- {
- /**
- * Create a new controller instance.
- *
- * @return void
- */
- public function __construct()
- {
- $this->middleware('auth:professor');
- }
-
- /**
- * Show the application dashboard.
- *
- * @return \Illuminate\Http\Response
- */
- public function index()
- {
- dd("professor.index");
- }
- }
ここで一旦動作を確認してみよう.Webサーバを再起動し,ログアウトした状態で /admin/home や /professor/home にアクセスすると,それぞれ /admin/login や /professor/login に転送されることが確認できるはずである.また,一般ユーザ (user) でログインしている状態でも /admin/home や /professor/home にアクセスするとやはりログイン画面に転送される.