Laravel で認証機能を自動生成する

2020/02/07

Laravel では artisanコマンドによって自動で認証機能(auth)を作成することができます。


php artisan make:auth

 
このコマンドを打つだけでユーザー登録画面やログイン画面を作成することができます。

今回は artisanコマンドでログイン画面を作成してその仕様について見てみます。(※バージョンは5.2です。)

なお、認証画面の自作に関してはチュートリアル中級で紹介しています。

 

INDEX

 

ログイン画面の作成

1.認証用のデータベースの作成

標準で用意されているマイグレーションファイルを利用します。

migrateコマンドを実行させるだけです。


php artisan migrate

 
このコマンドを実行すると

  • usersテーブル
  • password_resetsテーブル(パスワードリセット時に利用される)

が生成されます。

 

usersテーブル

 

password_resetsテーブル

 

2.artisanコマンドの実行

make:auth コマンドにより認証用の画面が自動的に作成されます。


php artisan make:auth

 
resources/views/auth ディレクトリにいくつかのビューファイルが追加されます。

  • login.blade.php ログイン用のフォーム
  • register.blade.php ユーザー登録用のフォーム
  • passwords/email.blade.php パスワードリセット用のメール送信フォーム
  • passwords/reset.blade.php パスワードリセット用の新パスワード登録フォーム
  • resources/views/layouts/app.blade.php 共通レイアウト

 

仕様確認

make:auth コマンドを実行すると、以下のような Route が生成されます。

 

TOPページ
URL:/
ルーティング:Route::get('/', function () { return view('welcome'); });

Laravelのスタートページが認証用画面に変わります。

 

HOMEページ
URL:home
ルーティング:Route::get('home', HomeController@index);

HOMEのページはログイン認証が必要なページになります。

未認証

 

認証済み

route.php を見てみると単に HomeController のindexに飛ばしているだけです。

HomeController を見ると以下のようにコンストラクタでauthミドルウェアが適用されています。


class HomeController extends Controller{
    //コンストラクタ
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function index()
    {
        return view('home');
    }}

 
authミドルウェア自体は、app\Http\Kernel.phpに記述されています。


    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class, // ←これ
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'auth.admin' => \App\Http\Middleware\AdminAuthenticate::class,
    ];

 
エイリアスが定義されていて、本体は \App\Http\Middleware\Authenicate::class になります。

Authenticate.php を開きます。


public function handle($request, Closure $next, $guard = null)
{
    //もし、ログインしてなかったら
    if (Auth::guard($guard)->guest()) {
             
        if ($request->ajax() || $request->wantsJson()) {
            return response('Unauthorized.', 401);
        } else {
            // loginにリダイレクト
            return redirect()->guest('login');
        }
    }

    return $next($request);
}

 

登録画面
URL:register
ルーティング:Route::get('register', Auth\AuthController@showRegistrationForm);

AuthControllershowRegistrationForm で処理されています。

しかし AuthController の中を見ても showRegistrationForm は見つかりません。

showRegistrationFormメソッドはトレイトに記述されています。


# app\Http\Controllers\Auth\AuthController.php
namespace App\Http\Controllers\Auth;
:
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers; // 名前空間
class AuthController extends Controller
{
  use AuthenticatesAndRegistersUsers, ThrottlesLogins; //トレイト
:

 
vendor\laravel\framework\src\iLLuminate\foundaton\Auth\AuthenticatesAndRegistersUsers.php を開きます。

しかし、AuthenticatesAndRegistersUsers.php を開くとさらにトレイト。


# Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers

namespace Illuminate\Foundation\Auth;

trait AuthenticatesAndRegistersUsers{
    use AuthenticatesUsers, RegistersUsers { // トレイト
        AuthenticatesUsers::redirectPath insteadof RegistersUsers;
        AuthenticatesUsers::getGuard insteadof RegistersUsers;
    }}

 
RegistersUsersトレイト ( vendor\laravel\frameworks\src\Illuminate\Foundation\Auth\RegistersUsers.php ) を開きます。

ここでやっと showRegistrationForm() が見つかります。

認証系のメソッド ( 登録・ログイン・ログアウト ・パスワードリセット・スロットル) はこのディレクトリ( vendor\laravel\frameworks\src\Illuminate\Foundation\Auth\ ) に実装されています。


# vendor\laravel\Illuminate\Foundation\Auth\RegistersUsers.php
:
    public function showRegistrationForm()
    {
        // registerView が定義されていればそこへビューを表示
        if (property_exists($this, 'registerView')) {
            return view($this->registerView);
        }

        //  定義されていなければ、resources\views\auth.register を表示
        return view('auth.register');
    }

 

ログアウト
URL:logout
ルーティング:Route::get('logout', Auth\AuthController@logout);

logout の本体も同様にトレイトとして格納されています。

vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php に記述されています。


    public function logout()
    {
        Auth::guard($this->getGuard())->logout();

        // redirectAfterLogout が定義されていればそのページにリダイレクト。
        // なければ / にリダイレクト。
        return redirect(property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout : '/');
    }

 

ログイン画面
URL:login
ルーティング:Route::get('login', Auth\AuthController@showLoginForm);

ルーティングのとおり、AuthControllershowLoginForm で処理されます。

本体はログアウトと同様に、vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php に記述されています。


    public function showLoginForm()
    {
        // loginViewが定義されていればそこに表示
        // なければ、auth.loginが表示
        $view = property_exists($this, 'loginView')
                    ? $this->loginView : 'auth.authenticate';

        if (view()->exists($view)) {
            return view($view);
        }

        return view('auth.login');
    }

 
ログインボタンを押すと、post送信でルーティングされます。

URL:login
ルーティング:Route::post('login', Auth\AuthController@login);

これも同様にトレイトのパスを追っていくと、 vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php に記述されていることがわかります。


    public function login(Request $request)
    {
         //バリデーション
        $this->validateLogin($request);

         //スロットル取得
        $throttles = $this->isUsingThrottlesLoginsTrait();
         
         //もし、規定の回数を超えていたら
        if ($throttles && $lockedOut = $this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }

         //認証情報取得
        $credentials = $this->getCredentials($request);

         //認証
        if (Auth::guard($this->getGuard())->attempt($credentials, $request->has('remember'))) {
            return $this->handleUserWasAuthenticated($request, $throttles);
        }

         //失敗だったらスロットルをカウントアップ
        if ($throttles && ! $lockedOut) {
            $this->incrementLoginAttempts($request);
        }

        return $this->sendFailedLoginResponse($request);
    }

 
認証がOKならログイン処理 (handleUserWasAuthenticated) が行われます。

その他にもスロットル処理が行われています。

これはログインの失敗を数え、一定の数を超えるとしばらくログインできないという処理です。

 

カスタマイズ

認証画面のカスタマイズについてです。

  • ログイン後のリダイレクト先
  • ログアウト後のリダイレクト先
  • ログインとなるDBの項目名
  • ログインスロットルとなるまで最高のログイン失敗回数
  • ログインスロットルとなってからの待ち秒数
  • 登録ページのビュー

このような変更は、Auth\AuthController.php のプロパティに記述することで可能です。

実例

class AuthController extends Controller
{
    protected $guard = 'users';
    protected $redirectTo = '/member/index';          // ログイン後のリダイレクト先
    protected $redirectAfterLogout = '/user/login';   // ログアウト後のリダイレクト先
    protected $username = 'email';                    // ログインとなるDBの項目名
    protected $maxLoginAttempts = 5;                  // ログインスロットルとなるまで最高のログイン失敗回数
    protected $lockoutTime = 60;                      // ログインスロットルとなってからの待ち秒数

    protected $registerView = "user/regist";          // 登録ページのView =>登録はAuthController外の方が良いかも

    use AuthenticatesAndRegistersUsers, ThrottlesLogins;

public function __construct()
{
:

 
以上です。

 

PHPフレームワーク Laravel入門

僕がはじめてLaravelを学習するために参考にしたサイトは、掌田津耶乃(しょうだつやの)さんの libro というサイトです。当時(2016年)、Laravel学習サイトの中でもこのサイトは群を抜いてわかりやすく説明されていたので、とても勉強になったのを覚えています。この本は掌田津耶乃さんが書いた本なので、わかりやすく解説されているだろうと kindle で購入しました。2019年7月の時点でいうと日本国内にて唯一の Laravel の良書と言っても良いかと思います。しかし、かなりわかりやすく解説されているとはいえ、PHP中級者以上のスキルは必要です。PHP自体の知識が乏しい方は独習PHP 第3版をあわせて購入することをお勧めします。

Amazonで詳細を見る

オススメ

 

本庄マサノリ

仕事で Laravel を使っています。気づいたことや新しい発見など情報を発信していきます。問い合わせはこちら

>> Twitter をフォローする

 

-チュートリアル, 上級, 初級