ユーザーログイン機能の作成 #Laravel頻出パターン #Laravel基礎
# はじめに
LaravelにはControllerより先に動くMiddleware(ミドルウェア)という機能が用意されています。
Middlewareを活用出来る例としては、表示前に年齢確認が必要なサイトの場合、年齢を確認する画面を挟む、といったケースが考えられます。
本稿ではMidlewareを利用して会員認証機能を作成していきます。データーベースなどを無しで作る、シンプルな認証機能を作っていきます。
用語
・セッション session()関数
・Middleware
# 設計
次のような機能で作成していきます。
・トップページ(/home)、サブページ(/sub)の2種類のページがある(/でアクセスすると/homeにリダイレクト)
・サブページを表示した場合、トップページに遷移する
・トップページは認証なしでも表示出来る
・トップページで認証済の場合は、「認証済です」と表示する
・トップページにログアウトボタンがあり、ボタンを押すと認証状態から解除される
# プロジェクトの作成
composer create-projectを使ってプロジェクトを作成します。今回は「login_sample」というプロジェクトを作ります。
composer create-project --prefer-dist laravel/laravel login_sample
cd login_sample
作成後にcdしてプロジェクトディレクトリに移動するのを忘れないようにしましょう
# Middlewareの作成
Middlewareの作成は「make:middleware」コマンドで行います。
php artisan make:middleware クラス名
今回はSimpleな認証機能ということでSimpleAuthクラスを作成します。
php artisan make:middleware SimpleAuth
「app/Http/Middleware/SimpleAuth.php」にクラスが作成されるのでこちらを編集します。
app/Http/Middleware/SimpleAuth.php
<?php
namespace App\Http\Middleware;
use Closure;
class SimpleAuth
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
return $next($request);
}
}
作成直後はこのようなコードになります。
handle()関数の中にMiddlewareのコードを書いていく形です。
# SimpleAuthの実装
PHPでは$_SESSIONを利用してセッションを使いますが、Laravelの場合はいくつかの便利な関数やクラスが提供されています。今回は便利なHelper関数のsession()を使います。
利用方法は次のようになります。
セッションから値を取り出す
$value = session("key");
セッションに値を設定
session->put("key", "value");
SimpleAuthは"simple_auth"がtrueの時、認証済とするMiddlewareとして作成します。
MiddlewareもControllerと同じredirect()関数を利用することが出来るのでこちらを利用して、
・認証済の時は引数に指定された$nextを処理する
・未認証の時はトップに遷移する
という形で実装します。
app/Http/Middleware/SimpleAuth.php
<?php
namespace App\Http\Middleware;
use Closure;
class SimpleAuth
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
//セッションの値を確認する
if(false == session("simple_auth")){
return redirect("/");
}
return $next($request);
}
}
Middlewareの作成はこちらで完了です。
Middlewareを利用するには作成後、いくつかの手順を取る必要があります。
# Middlewareの有効化(Kernelに登録)
まずは作成したSimpleAuthをKernelに登録します。
Kernelは核を意味する単語で、Laravelフレームワークは高機能なため、Webアプリケーション用のHttpカーネルやサーバー内の処理を行うConsoleカーネルなど、複数の機能に別れて作られています。
LaravelにおいてWebアプリケーションの立ち上げ、処理、終了を担うのがこのHttpカーネルです。
app/Http/Kernel.phpを編集し、「$routeMiddleware」にSimpleAuthを追記します。
app/Http/Kernel.php
class Kernel extends HttpKernel
{
(略)
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
//SimpleAuthを追加
'simple_auth' => \App\Http\Middleware\SimpleAuth::class
];
}
「key => クラス名」の形で設定を行います。
続いて、このkeyを利用してルーティングの設定を行います。
# ルーティングの設定
動作確認を含めて、次のルーティングを設定します。
・/にアクセス -> /homeにリダイレクト
・/home -> view("top")を表示
・/sub -> view("sub")を表示
・/subでSimpleAuthを利用する
routes/web.php
Route::get('/', function () {
return redirect('home');
});
Route::get('/home', function () {
return view('top');
});
Route::get('/sub', function () {
return view('sub');
})->middleware("simple_auth");
ルーティングでMiddlewareを有効にする時は「->middleware("key")」を後ろに追加します。
先程「simple_auth」というkeyでSimpleAuthクラスを有効にしたので引数には「simple_auth」を指定しています。
これで指定したルーティングにSimpleAuthミドルェアを関連付けることが出来るようになりました。
# 動作確認
動作確認用にテンプレートを用意します。それぞれ内容がわかる簡易のものです。
resources/views/top.blade.php
これはTOPです。
<a href="{{ url('/sub') }}">sub</a>
resources/views/sub.blade.php
このページは認証後に表示されます。
ターミナルから下記コマンドを入力して、開発サーバーを起動します。
php artisan serve
ブラウザで開いてsubページに遷移しようとすると戻されることを確認しましょう。
# ログイン機能の作成
subページを表示出来るようにログイン機能を作成します。
まずは、ログインフォーム用のテンプレートを作成します。
views/part/login_form.blade.php
@if ($errors->any())
<div style="color:red;">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form method="post" action="{{ url('login') }}">
@csrf
<div>
ID: <input type="text" name="user_id" value="" />
</div>
<div>
PASS: <input type="password" name="password" value="" />
</div>
<input type="submit" value="ログイン" />
</form>
フォームの前にエラーメッセージを表示するようにしてあります。エラー表示については掲示板を作ろうのこちらの記事をを参考にしてください。
ログインフォームの遷移先はloginに設定しておきます。
次に、トップページのテンプレートを編集し、ログインフォームを表示します。
resources/views/top.blade.php
これはTOPです。
<a href="{{ url('/sub') }}">sub</a>
@include("part.login_form")
# ログイン機能の作成 Controllerの作成
ログインフォームの遷移先のControllerを作成し、ルーティングに登録していきます。
make:controllerコマンドを使ってログイン用のSimpleLoginControllerクラスを作成します。
php artisan make:controller SimpleLoginController
SimpleLoginControllerはログインフォームからの遷移を処理するlogin()関数を追加します。
app/Http/Controllers/SimpleLoginController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class SimpleLoginController extends Controller
{
function login(Request $request){
//入力内容をチェックする
$user_id = $request->input("user_id");
$password = $request->input("password");
//ログイン成功
if($user_id == "hogehoge" && $password == "fugafuga"){
session()->put("simple_auth", true);
return redirect("/sub");
}
//ログイン失敗
return redirect("/home")->withErrors([
"login" => "ユーザーIDまたはパスワードが違います"
]);
}
}
$request->input("xxx")を使ってname="user_id"の入力値、name="password"の入力値を受け取ります。
session->put("simple_auth", true);
$user_idがhogehoge、$passwordがfugafugaの時はログイン成功として、セッションの「simple_auth」にtrueを設定します。その後サブページを表示します。
//ログイン失敗
return redirect("/home")->withErrors([
"login" => "ユーザーIDまたはパスワードが違います"
]);
認証に失敗した時はトップページにリダイレクトします。この時withErrorsでエラーメッセージを渡すようにしています。
Controllerの作成が終わったら、/loginとSimpleLoginControllerのルーティングを設定します。
routes/web.php
//ログイン処理
Route::post('/login', 'SimpleLoginController@login');
ブラウザで確認してユーザー名とパスワードを間違えた時にエラーメッセージが出ることと、ログインに成功した時に/subに遷移してサブページが表示されることを確認してください。
# ログアウト機能の作成
トップページのテンプレートを編集し、ログインしている時は「認証済です」の表示とログアウトをフォームを、ログインしていない時はログインフォームを表示するようにします。
テンプレートの中でもsession()関数は使えるので@if構文を使って次のように書き換えます。
resources/views/top.blade.php
これはTOPです。
<a href="{{ url('/sub') }}">sub</a>
@if(session("simple_auth"))
<p>認証済です。</p>
<form method="post" action="{{ url('logout') }}">
@csrf
<input type="submit" value="ログアウト" />
</form>
@else
@include("part.login_form")
@endif
@if〜@else〜@endifを使ってログイン済(simple_authがtrue)かどうかで表示を切り分けています。
ログアウトフォームはlogoutに設定しています。次にログアウトフォームの遷移先を処理するSimpleLogoutControllerを作成します。
Controllerの作成は「make:controller」コマンドから行います。
php artisan make:controller SimpleLogoutController
app/Http/Controllers/SimpleLogoutController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class SimpleLogoutController extends Controller
{
function logout(){
session()->forget("simple_auth");
return redirect("/");
}
}
session()->forget("key")関数を使うことで、keyで指定した項目を削除することが出来ます。
ログアウト機能はsimple_authを削除することで実装しています。
続いて、ルーティングを設定し、ログアウトフォームの遷移先をSimpleLogoutControllerと関連付けます。
routes/web.php
//ログアウト
Route::post('/logout', 'SimpleLogoutController@logout');
ブラウザで確認し、ログイン・ログアウトが出来ることを確認してください。
# まとめ
本稿を通してセッションの利用方法、Middlewareの作成と利用方法について学びました。
ログインIDとパスワードはControllerクラスの中に直接書いていますが、ここをデーターベースを利用した形にすることが一般的です。
Laravelには標準機能で認証機能を作成することが出来ますが、今回はMiddlewareを使った最小限の形で作ってみました。このようなセッションの値の有無でユーザーの状態を分ける処理はWebアプリケーションではよく出てきます。
すでにある機能を作ることは車輪の再発明と言って本来避けるべき行為ですが、実際に自分で作ってみないとわからない部分もあります。
「こういうことをしたいときにMiddlewareでやると良い」とわかるようにはかなりの熟練が必要になると思います。
サンプルコードをGitHubで公開しています。
おつかれさまでした!
---
完成まで突っ走る意気込みです。サポートしていただけると非常に嬉しいです。応援よろしくお願いします。