初めてのLaravel 5.1 : (28) 認証

login
Laravel 5.1 ではプロジェクトを作成した時点で、ユーザ登録、ログイン認証、パスワード再設定の機能がすぐ使えるように、コントローラが用意されています。しかし、これらの機能を使うためのルーティング設定やビューの作成は自分で行う必要があります。今回は、ユーザ登録とログイン認証の実装を行います。


マイグレーション

Laravelプロジェクトを作成した時に、デフォルトでユーザーとパスワード再設定用の 2つのマイグレーションファイルが作成されています。マイグレーションを1度でも実行済であれば、必要なデータベースの項目は既に出来ています。

忘れてしまった人は、以前にやった、「マイグレーションでdbのバージョン管理」を振り返ってみてください。


Routing

routes.phpに以下のようにルートを追加します。

<?php // app/Http/routes.php

...

// Authentication routes...
Route::get('auth/login', 'Auth\AuthController@getLogin');
Route::post('auth/login', 'Auth\AuthController@postLogin');
Route::get('auth/logout', 'Auth\AuthController@getLogout');

// Registration routes...
Route::get('auth/register', 'Auth\AuthController@getRegister');
Route::post('auth/register', 'Auth\AuthController@postRegister');

// Route::controller('auth', 'Auth\AuthController');  // ①

5つのルートを追加しました。
上記の5つを登録する代わりに①の Implicit Controller(暗黙コントローラ)を使うこともできます。

artisan コマンドでルートを確認します。

php artisan route:list
+--------+----------+--------------------------+------------------+-------------------------------------------------------+------------+
| Domain | Method   | URI                      | Name             | Action                                                | Middleware |
+--------+----------+--------------------------+------------------+-------------------------------------------------------+------------+
|        | GET|HEAD | auth/login               |                  | App\Http\Controllers\Auth\AuthController@getLogin     | guest      |
|        | POST     | auth/login               |                  | App\Http\Controllers\Auth\AuthController@postLogin    | guest      |
|        | GET|HEAD | auth/logout              |                  | App\Http\Controllers\Auth\AuthController@getLogout    |            |
|        | GET|HEAD | auth/register            |                  | App\Http\Controllers\Auth\AuthController@getRegister  | guest      |
|        | POST     | auth/register            |                  | App\Http\Controllers\Auth\AuthController@postRegister | guest      |
+--------+----------+--------------------------+------------------+-------------------------------------------------------+------------+

※上記の表は auth に絞って表示しています。


ナビゲーション

ナビゲーションビューを修正します。

{{-- resouces/views/navbar.blade.php --}}

<nav class="navbar navbar-default">
	<div class="container">
		<div class="navbar-header">
			<!-- スマホやタブレットで表示した時のメニューボタン -->
			<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
				...
			</button>

			<!-- ブランド表示 -->
			<a class="navbar-brand" href="/">My Blog</a>
		</div>

		<!-- メニュー -->
		<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">

			<!-- 左寄せメニュー -->
			<ul class="nav navbar-nav">
				<li>{!! link_to_route('articles.index', 'Blog') !!}</li>
				<li><a href="/contact">Contact</a></li>
				<li><a href="/about">About</a></li>
			</ul>

			<!-- 右寄せメニュー -->
			<ul class="nav navbar-nav navbar-right">

				@if (Auth::guest())
					{{-- ログインしていない時 --}}

					<li><a href="/auth/login">Login</a></li>
					<li><a href="/auth/register">Register</a></li>
				@else
					{{-- ログインしている時 --}}

					<!-- ドロップダウンメニュー -->
					<li class="dropdown">
						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
							{{ Auth::user()->name }}
							<span class="caret"></span>
						</a>
						<ul class="dropdown-menu" role="menu">
							<li><a href="/auth/logout">Logout</a></li>
						</ul>
					</li>
				@endif
			</ul>
		</div><!-- /.navbar-collapse -->
	</div><!-- /.container-fluid -->
</nav>

修正したのは右寄せメニューの部分です。

  • Authファサードを使用してログインユーザーの情報にアクセスしています。
  • Auth::guest() でログイン中かどうか判断し、メニューの表示を切り替えます。
  • Auth::user()->name でログインユーザー名を取得しています。
  • ルート定義に基づいて、Login, Register, Logoutのリンクパスを指定しました。

View

ログイン認証、ユーザー登録のビューを以下のように作成します。

./resources
└── views
    └── auth
         ├── login.blade.php
         └── register.blade.php

login.blade.php

{{-- resources/views/auth/login.blade.php --}}

@extends('layout')

@section('content')
<div class="container-fluid">
  <div class="row">
    <div class="col-md-8 col-md-offset-2">
      <div class="panel panel-default">
        <div class="panel-heading">Login</div>
        <div class="panel-body">
          @if (count($errors) > 0)
            <div class="alert alert-danger">
              <strong>Whoops!</strong> There were some problems with your input.<br><br>
              <ul>
                @foreach ($errors->all() as $error)
                  <li>{{ $error }}</li>
                @endforeach
              </ul>
            </div>
          @endif

          <form class="form-horizontal" role="form" method="POST" action="/auth/login">
            {{-- CSRF対策--}}
            <input type="hidden" name="_token" value="{{ csrf_token() }}">

            <div class="form-group">
              <label class="col-md-4 control-label">E-Mail Address</label>
              <div class="col-md-6">
                <input type="email" class="form-control" name="email" value="{{ old('email') }}">
              </div>
            </div>

            <div class="form-group">
              <label class="col-md-4 control-label">Password</label>
              <div class="col-md-6">
                <input type="password" class="form-control" name="password">
              </div>
            </div>

            <div class="form-group">
              <div class="col-md-6 col-md-offset-4">
                <div class="checkbox">
                  <label>
                    <input type="checkbox" name="remember"> Remember Me
                  </label>
                </div>
              </div>
            </div>

            <div class="form-group">
              <div class="col-md-6 col-md-offset-4">
                <button type="submit" class="btn btn-primary" style="margin-right: 15px;">
                  Login
                </button>

                <a href="/password/email">Forgot Your Password?</a>
              </div>
            </div>
          </form>
        </div><!-- .panel-body -->
      </div><!-- .panel -->
    </div><!-- .col -->
  </div><!-- .row -->
</div><!-- .container-fluid -->
@endsection

register.blade.php

{{-- resources/views/auth/register.blade.php --}}

@extends('layout')

@section('content')
<div class="container-fluid">
  <div class="row">
    <div class="col-md-8 col-md-offset-2">
      <div class="panel panel-default">
        <div class="panel-heading">Register</div>
        <div class="panel-body">
          @if (count($errors) > 0)
            <div class="alert alert-danger">
              <strong>Whoops!</strong> There were some problems with your input.<br><br>
              <ul>
                @foreach ($errors->all() as $error)
                  <li>{{ $error }}</li>
                @endforeach
              </ul>
            </div>
          @endif

          <form class="form-horizontal" role="form" method="POST" action="/auth/register">
            {{-- CSRF対策--}}
            <input type="hidden" name="_token" value="{{ csrf_token() }}">

            <div class="form-group">
              <label class="col-md-4 control-label">Name</label>
              <div class="col-md-6">
                <input type="text" class="form-control" name="name" value="{{ old('name') }}">
              </div>
            </div>

            <div class="form-group">
              <label class="col-md-4 control-label">E-Mail Address</label>
              <div class="col-md-6">
                <input type="email" class="form-control" name="email" value="{{ old('email') }}">
              </div>
            </div>

            <div class="form-group">
              <label class="col-md-4 control-label">Password</label>
              <div class="col-md-6">
                <input type="password" class="form-control" name="password">
              </div>
            </div>

            <div class="form-group">
              <label class="col-md-4 control-label">Confirm Password</label>
              <div class="col-md-6">
                <input type="password" class="form-control" name="password_confirmation">
              </div>
            </div>

            <div class="form-group">
              <div class="col-md-6 col-md-offset-4">
                <button type="submit" class="btn btn-primary">
                  Register
                </button>
              </div>
            </div>
          </form>
        </div><!-- .panel-body -->
      </div><!-- .panel -->
    </div><!-- .col -->
  </div><!-- .row -->
</div><!-- .container-fluid -->
@endsection

以前にBootstrapを導入しているので、BootstrapのCSSで装飾した画面にしています。

ログイン認証、ユーザー登録のビューはどちらもFormを持っています。
以前にFormを作成した時は、laravelcollective/html パッケージのペルパー関数を使用しましたが、今回は formタグを直打ちしています。この場合、CSRF対策としてのトークンを自分で埋め込む必要があります。また、入力エラーがあって、フォームが再表示された時に、直前に入力された値を old()メソッドを使って復帰させる必要もあります。

{{-- CSRF対策 --}}
<input type="hidden" name="_token" value="{{ csrf_token() }}">

...

{{-- 直前の入力値の復帰 --}}
<input type="text" class="form-control" name="name" value="{{ old('name') }}">

formタグを記述する時に、laravelcollective/html のヘルパー関数を使うか、HTMLを直打ちするかは、好みに応じて決めてください。ヘルパー関数を使った場合は、CSRF対策のトークンを自動的に埋め込んでくれますが、ヘルパー関数の使い方を覚える必要があります。HTMLタグを直打ちした方が分かりやすく感じる方もいると思います。しかし、HTMLタグを直打ちした場合、CSRF対策のトークンの埋め込みを忘れてしまうミスが増えそうです。Form::open(), Form::close()だけはヘルパー関数を使用して(CSRF対策のトークンを自動埋め込みして)、後は全てHTMLタグを直打ちするという方法もあります。


Controller

AuthController.php を修正し、ユーザー登録後やログイン後のリダイレクト先を指定します。リダイレクト先を指定しなかった場合は、”/home”へリダイレクトするように、AuthenticatesAndRegistersUsers トレイトの中で、ハードコーディングされています。AuthenticatesAndRegistersUsers トレイトの中身はざっと目を通しておくことをお薦めします。

// app/Http/Controllers/Auth/AuthController.php

class AuthController extends Controller {
	use AuthenticatesAndRegistersUsers;

	protected $redirectTo = '/articles'; // 追加。登録後やログイン後のリダイレクト先

	public function __construct()
	{
		$this->middleware('guest', ['except' => 'getLogout']);
	}
	
	...
}

ユーザー登録

実際にユーザー登録をしてみます。

register

  1. ナビゲーションで “Register” をクリックしユーザー登録画面を表示します。
  2. ユーザー情報を入力し、登録します。
  3. 記事一覧が表示され、ナビゲーションの右上にユーザー名が表示されます。

artisan コマンドで、DBにユーザーデータが登録されたか見てみます。

$ php artisan tinker

>>> \App\User::all()->toArray();
=> [
       [
           "id"         => "2",
           "name"       => "who",
           "email"      => "who@sample.com",
           "created_at" => "2015-03-21 12:02:30",
           "updated_at" => "2015-03-21 12:02:30"
       ]
   ]
>>> 

ユーザーデータが1件登録されていました。成功です。


ログアウト

次にログアウトをしてみます。

  1. ナビゲーションの右上のユーザー名をクリックし、ドロップダウンメニューからログアウトします。
  2. ナビゲーションの右に、”Login”と”Register”が表示されます。

ログイン

login

先ほど登録したユーザーデータでログインしてみます。

  1. ナビゲーションで”Login”をクリックし、ログイン画面を表示します。
  2. メールアドレスとパスワードを入力しログインします。
  3. 記事一覧が表示され、ナビゲーションの右上にユーザー名が表示されます。

まとめ

ユーザー登録とログイン、ログアウトが出来るようになりました。
ユーザー登録とログイン認証のコントローラが初めから入っているのは良いのですが、ルーティング、ビューの作成を行わなければならず、ちょっと分かりづらかったです。この辺の手順の事は公式サイトのドキュメントに記述されていますので、そちらもチェックして置くことをお薦めします。

http://laravel.com/docs/5.1/authentication

ユーザー登録時に確認メールを送信して、本人確認をしたい方は以下の記事をご覧ください。
laravel 5.1のユーザー登録で確認メールを送る【前篇】

初めてのLaravel 5.1 : (28) 認証」への1件のフィードバック

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中