見出し画像

Laravel学習記録 #027 独自認証を試して学ぶ

Laravelの認証機能について学習したものをまとめてます。
Laravel Breezeなどのスターターキットを使わずに独自でログイン機能を作成してみます。

独自のログイン機能を作成してみる

独自のと言っても、Laravelに備わった機能の範囲で実現します。
・認証テーブルをusersではなくaccountsにする
・emailの代わりに、アカウントIDにする
・パスワードはLaravel標準のハッシュを使う
とします。

テーブルの作成

Userモデルの代わりとなるAccountモデルを作成します。
マイグレーションファイルは以下の通りです。
テストデータも一緒に挿入します。

database/migrations/xxxx_xx_xx_xxxxxx_create_accounts_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('accounts', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('account_id');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });

        // テストデータ挿入
        DB::table('accounts')->insert([
            'name' => 'サンプル太郎',
            'account_id' => '0001',
            'email' => 'sample@example.com',
            'email_verified_at' => now(),
            'password' => bcrypt('password'),
            'remember_token' => Str::random(10),
            'created_at' => now(),
            'updated_at' => now(),
        ]);
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('accounts');
    }
};

ここまでで反映させましょう。

php artisan migrate


モデルの実装

標準ではUserモデルを使用していますが。
今回はAccountモデルを使います。
Userモデル以外を認証用と紐づける場合は以下のインターフェースの実装が必要です。

use Illuminate\Contracts\Auth\Authenticatable;

と言ってもトレイトがあるので下記を使います。

use Illuminate\Auth\Authenticatable;

実際にアカウントモデルに適用します。

app/Models/Account.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Auth\Authenticatable as AuthenticableTrait;

class Account extends Model implements Authenticatable
{
    use HasFactory;
    use AuthenticableTrait;
}


コントローラーの作成

ではコントローラーに認証用の処理を書いていきます。
認証にはAuthファサードのattemptメソッドを使います。

app/Http/Controllers/AccountController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class AccountController extends Controller
{
    public function index()
    {
        return view('account-login');
    }

    public function login(Request $request)
    {
        $credentials = $request->only(['account_id', 'password']);
        
        if (Auth::attempt($credentials)) {
            $request->session()->regenerate();

            return redirect()->intended('/home');
        }

        return back();
    }

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

attemptメソッドには連想配列で
'絞り込むやつ' => '値', と 'password' => '値'
を渡してあげつ必要があります。
passwordのキーは固定のためもし命名が違う場合は他で調節が必要そうです。
今回はaccount_idで絞り込み、passwordで認証可否が決まりますので
onlyメソッドで取得した値をそのまま渡しています。

 ビューとルートの作成

続いてviewを作成して、ルートを設定します。
resources/views/account-login.blade.php

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Laravel学習記録</title>
</head>
<body>
    <h1>ログイン</h1>
    
    <form action="{{route('login')}}" method="post">
        @csrf
        <label for="">アカウントID</label>
        <input type="text" name="account_id">
        <br>
        <label for="">パスワード</label>
        <input type="text" name="password">
        <br>
        <input type="submit" value="ログイン">
    </form>
    
</body>
</html>


resources/views/home.blade.php

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Laravel学習記録</title>
</head>
<body>
    <h1>ログイン成功の画面</h1>
</body>
</html>


routes/web.php

<?php

use App\Http\Controllers\AccountController;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/

Route::get('login', [AccountController::class, 'index']);
Route::post('login', [AccountController::class, 'login'])->name('login');

Route::middleware('auth')->group(function () {
    Route::get('home', [AccountController::class, 'home']);
 });


config設定

最後にconfig/auth.phpを修正します。
Accountモデルを適用するようにしましょう。

'defaults' => [
        'guard' => 'web',
        'passwords' => 'accounts',
    ],

'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'accounts',
        ],
    ],

'providers' => [
        'accounts' => [
            'driver' => 'eloquent',
            'model' => App\Models\Account::class,
        ],
    ],


これでログイン画面(/login)から認証機能の確認ができるはずです。
テストデータで挿入した通りアカウントIDを「0001」パスワードを「password」とすることで認証ができます。
それ以外の場合はログイン画面にリダイレクトするはずです。


バリデーションなどは省きましたが、大まかにはこれで手作業での認証機能を作成できますね。

この記事が気に入ったらサポートをしてみませんか?