【3ステップで解決】Laravelから既存テーブルでログインする方法

こんにちは。フリーランス・コンサルタント&エンジニアの 九保すこひ です。

さてさて、(数えてないですが)活動期間を考えると、おそらく100回以上の案件をこなしてきました。

プログラミングが好きだから、どの開発も興味深いんです。
ただ、たまに「うーん、なるほど😅」となるものあります。

それは・・・・・・

  • 先代のコードがごちゃついている
  • 難読化されたコードを解析しなきゃいけない
  • 開発メンバーが退社していて、質問できない

つまり、0からの開発ではなく、既存のルールの中で作業するときは、なかなか厄介だったりしますよね。

そして今回のテーマも同じく、

既存システムのDBでログイン

です。

こうなるとDBテーブルの構成が違うので、そのまま新システムのログイン認証に使えません。

そこで!

今回は「たった3ステップ」で既存DBテーブルを使ったログインができるようにしてみます。

今回は以下のような方にお届けします。

  • 既存システム+Laravelでログインする基礎が知りたい
  • 既存システム+Laravelのログインを出来るだけ簡単に実装したい
  • 既存システム+Laravelのログインをなんならコピペだけで済ませたい

ぜひ最後まで見てくださいね!

「Twitterの趣味アカウント、
いいねが最大40ぐらい
つくようになりました!!!」

開発環境: Laravel 11.x

【前提として】Laravelで既存のDB認証する環境について

1. md5でハッシュ化されたパスワードを想定してます

ハッシュ化とは元の文字列を違う形に変換することです。
こうすることで、もしデータベースを盗み見られてもパスワードが推測できないというわけですね。

今回、パスワードのハッシュにはmd5形式を使います。

なお、md5のハッシュは比較的推測しやすいので、セキュリティ能力は低いとされています。実際にはbcryptなど、より強固なハッシュ化をすべきです。

【例】passwordをハッシュ化すると、5f4dcc3b5aa765d61d8327deb882cf99になります。

2. 既存データベースが用意されている

今回は、以下テーブルを既存データベースとして作業を進めていきます。

テストデータはこちら。

もしSQL文でテーブルを作りたい場合は、以下を使ってください。

DROP TABLE IF EXISTS `authUser`;
CREATE TABLE `authUser` (
`user_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `user_password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `timestamp` int NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `authUser` (`user_id`, `user_password`, `user_name`, `timestamp`) VALUES
('000001',  '5f4dcc3b5aa765d61d8327deb882cf99',    '山田太郎',    1718742563),
('000002',  '5f4dcc3b5aa765d61d8327deb882cf99',    '佐藤次郎',    1718742563);

3. Laravel Breezeでログイン機能がインストールされている

ログイン機能(Laravel Breeze)は先にインストールしておいてください。

以下3つのコマンドで完了できます。

composer require laravel/breeze --dev
php artisan breeze:install
php artisan migrate

念のため、マイグレーションも実行しておいてください。

ではここから3ステップの開始です。
細かなところもありますが、根本はシンプルなのでぜひ試してみてください。

【ステップ1:モデル】Laravelから既存テーブルにアクセスできるようにする

既存テーブルに新システム(Laravel)からアクセスするためにモデルを作成します。

名前は「OldUser」です。
以下のコマンドを実行してください。

php artisan make:model OldUser

ファイルが作成されるので中身を以下のようにします。

app/Models/OldUser.php

<?php

namespace App\Models;

use Carbon\Carbon;
use Illuminate\Foundation\Auth\User as Authenticatable;

class OldUser extends Authenticatable
{
    protected $primaryKey = 'user_id';
    protected $keyType = 'string';
    protected $authPasswordName = 'user_password';
    protected $connection = 'old_mysql';
    protected $table = 'authUser';
    protected $fillable = [
        'timestamp',
    ];
    protected $hidden = [
        'user_password',
    ];
    protected $appends = [
        'id',
        'name',
        'created_at',
        'updated_at',
    ];

    // Accessor
    public function getIdAttribute() // $model->id
    {
        return $this->user_id;
    }

    public function getNameAttribute() // $model->name
    {
        return $this->user_name;
    }

    public function getCreatedAtAttribute() // $model->created_at
    {
        return new Carbon($this->timestamp);
    }

    public function getUpdatedAtAttribute() // $model->updated_at
    {
        return new Carbon($this->timestamp);
    }
}

重要な点は2つです。

  • 既存テーブルのカラム構造をセットする(差を吸収する)
  • 既存テーブルにはないカラムをAccessorとして使えるようにする

Accessorとは】

元々テーブルにはないカラムを擬似的に存在しているようにする機能です。
例えば姓名(first_name, last_name)の2カラムがある場合、結合して$user->full_nameとして取得したりできます。

今回Accessorとして追加した値は以下の4つです。

  • id: $user->id として使えるようにしてます
  • name: $user->name
  • created_at: $user->created_at
  • updated_at: $user->updated_at

【ステップ2:プロバイダー】Laravelで既存テーブルと調整するプロバイダーをつくる

1. カスタムプロバイダーをつくる

繰り返しですが、既存システムとLaravelのテーブル構成は別ですから、そのままログインすることはできません。

この差を調整してくれる専用プロバイダーをつくります。

通常はsrc/Illuminate/Auth/EloquentUserProvider.phpが使われますが、新しいものをつくります。

app/Providers/CustomUserProvider.php

<?php

namespace App\Providers;

use App\Models\OldUser;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;

class CustomUserProvider implements UserProvider
{
    private OldUser $model;

    public function __construct()
    {
        $this->model = new OldUser();
    }

    public function retrieveById($identifier)
    {
        $primary_key = $this->model->getAuthIdentifierName();

        return $this->model->where($primary_key, $identifier)->first(); // ここがないとログインできない
    }

    public function retrieveByToken($identifier, $token)
    {}

    public function updateRememberToken(UserContract $user, $token)
    {}

    public function retrieveByCredentials(array $credentials)
    {
        $primary_key = $this->model->getAuthIdentifierName();
        $user_id = $credentials[$primary_key];

        return $this->model->where($primary_key, $user_id)->first();
    }

    public function validateCredentials(UserContract $user, array $credentials)
    {
        $password_name = $this->model->getAuthPasswordName();
        $plain = $credentials[$password_name];

        return md5($plain) === $user->getAuthPassword(); // 送信されたパスワードをmd5でハッシュ化して比較
    }

    public function rehashPasswordIfRequired(UserContract $user, array $credentials, bool $force = false)
    {}
}

データ取得やパスワード・チェックをしています。
トークンは既存テーブルには存在していないので、コードが空になっています。

※プロフィール編集ページなどで必要になるかも…🤔

2. カスタムプロバイダーを定義する

作成したプロバイダーは、Laravelからすると存在していない状態ですので、定義をしましょう。

app/Providers/AppServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Auth;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Auth::provider('custom', function() {

            return new CustomUserProvider();

        });
    }
}

3. カスタムプロバイダーを有効にする

先ほど定義をしましたが、まだCustomUserProviderは無効のままです。
以下のように有効にしてください。

config/auth.php

// 省略

'providers' => [
    'users' => [
        'driver' => 'custom',
        'model' => env('AUTH_MODEL', App\Models\OldUser::class),
    ],

// 省略

「custom」という部分はAppServiceProviderで定義したものです。
お好みで変更してください。

【ステップ3:各種設定】Laravelで既存テーブル・ログインの設定をする

1. 既存データベースの接続情報をセットする

既存データベースへ接続する情報が入っていないので、「old_mysql」として定義しておきます。

config/database.php

// 省略

'old_mysql' => [
    'driver' => 'mysql',
    'url' => null,
    'host' => '127.0.0.1',
    'port' => '3306',
    'database' => 'old_system',
    'username' => 'your-username',
    'password' => 'your-password',
    'unix_socket' => '',
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => '',
    'prefix_indexes' => true,
    'strict' => true,
    'engine' => null,
    'options' => extension_loaded('pdo_mysql') ? array_filter([
        PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
    ]) : [],
],

// 省略

※なお、本来は.envに書いておくべきですが今回はテストなので直書きしています。

2. ログイン時のバリデーションを調整する

通常、Laravelでログインするときは以下2つの情報でログインします。

  • メールアドレス
  • パスワード

しかし、今回は以下2つでのログインです。

  • ユーザーID
  • パスワード

となるとバリデーションの「メールじゃないとダメ!」という部分が不要になるので、除去しておきましょう。

app/Http/Requests/Auth/LoginRequest.php

// 省略

public function rules(): array
{
    return [
        'email' => ['required', 'string'], // 👈 emailを削除
        'password' => ['required', 'string'],
    ];
}

// 省略

3. ログインフォームを調整

これは小さな部分ですが、初期状態だとメールアドレスを想定しています。

resources/views/auth/login.blade.php

<x-text-input id="email" class="block mt-1 w-full" type="email" ...

しかし、これでは@マークを入力しないと送信できない制約があるので、「text」へ変更します。

resources/views/auth/login.blade.php

<x-text-input id="email" class="block mt-1 w-full" type="text"

【実行テスト】既存データベースでもログインできるかチェックする

では実際にテストしてみましょう❗

1. ブラウザでアクセスする

「https://******/login」へアクセスすると、ログインフォームが表示されます。

2. 間違ったログイン情報を送信してみる

テストですので間違ったログイン情報を送信してバリデーションが効いているか確かめておきます。

以下の情報を送信してみましょう。

  • ID: test
  • PW: testxxx

すると・・・・・・

想定通りログインできず、エラーが表示されました。

3. 正しいログイン情報を送信する

次に以下の正しい情報でログインしてみましょう。

  • ID: 000001
  • PW: password

どうなるでしょうか・・・・・・

ログイン後のダッシュボードが表示されました。

Accessorを作っているので名前もきちんと表示されています。

4. ログアウトできるか確認する

最後にログアウトもできるか確認しておきます。
ページ右上にあるLog outをクリックしてください。

うまくいくでしょうか・・・・・・

ログアウトできて、Laravelのトップページに移動しました。

すべて成功です😊✨

【ご提案】既存システムを稼働している企業様へ

もしかすると、以下3つのような悩みはないでしょうか?

「既存システムがあるけど、古いシステムなので改修ができない」
「既存システムに新しい機能がほしいけど、技術者がいない」
「新システムへ移行したいけど、やり方がわからない」

答えがYesでしたら、今回のようにLaravelと既存データベースを連携させて新システムを開発することが可能です。

もしそういったご希望がありましたら、ぜひお問い合わせからご連絡ください。無料でオンライン面談させていただきます。

お待ちしております!😊✨

おわりに

今回は既存データベースと最新Laravelでログイン機能を実装する方法を紹介しました。

特に既存システムは稼働してるけど、古いシステムの場合は開発者が退職していたり、すでに技術者自体が少ない可能性もあります。

そんな場合は今回のテクニックを使えば簡単にログインを実装することができます。

もし将来的に「既存システム + Laravel新システム」の開発があっても今回の記事を使えば、比較的楽に対応できるんじゃないでしょうか。

ぜひブックマークしておいてくださいね。

ではでは〜❗

「今日はゆっくりできそうだぞ!
からの怒涛のメール受信
ってあるあるですよね😅」

このエントリーをはてなブックマークに追加       follow us in feedly  
開発のご依頼お待ちしております
開発のご依頼はこちらから: お問い合わせ
どうぞよろしくお願いいたします! by 九保すこひ