TKngDisuke
@TKngDisuke (大輔 徳永)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

[Laravel]マルチ認証機能がうまくいかない

解決したいこと

[Laravel]マルチ認証機能がうまくいかない
うまくいかないところが2つあり、
○マルチ認証を開発しているのですが、認証ページでデータベースに登録しているメールアドレス、パスワードを用いてログインしようとしても認証されません。
○またログインしていないときの強制リダイレクトができません

こちらのサイトを利用して実装しました。
https://blog.capilano-fw.com/?p=8159

環境Laravel8、MAMPでApcheを利用、Mysqlを用いてモバイルオーダーアプリを作りました。
ログイン機能はJetstreamを利用しており、マルチ認証機能を実装しようとしています。

発生している問題・エラー

正しく認証しない
2つのユーザーデータを作り、ログインしようとしましたが、うまくログインができませんでした。
multi_login画面で管理者ではない選択でUserログインはうまくいきましたが、管理者ログインはできていません。
スクリーンショット 2021-10-20 8.21.19.png

例)
Controller

MultiAuthController.php
<?php

namespace App\Http\Controllers;
use Illuminate\Http\Request;

class MultiAuthController extends Controller
{
    public function showLoginForm() {

        return view('multi_auth.login');

    }
    public function index() {

        return 'OK';

    }

    public function login(Request $request) {

        $credentials = $request->only(['email', 'password']);
        $guard = $request->guard;

        if(\Auth::guard($guard)->attempt($credentials)) {

            return redirect($guard .'/dashboard'); // ログインしたらリダイレクト

        }

        return back()->withErrors([
            'auth' => ['認証に失敗しました']
        ]);
    }
}

ログインしていないときの強制リダイレクト

Authenticate.php
<?php

namespace App\Http\Middleware;

use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Support\Str;

class Authenticate extends Middleware
{
    /**
     * Get the path the user should be redirected to when they are not authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return string|null
     */
    protected function redirectTo($request)
    {
        if (! $request->expectsJson()) {

            $uri = $request->path();

            // URIが以下3つから始まる場合
            if(Str::startsWith($uri, ['administrators/'])) {

                return 'multi_login';

            }

            return route('login');
        }
    }
}

Model

Administrator.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;

class Administrator extends Authenticatable
{
    use HasFactory;
}

configファイルの認証

auth.php
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Defaults
    |--------------------------------------------------------------------------
    |
    | This option controls the default authentication "guard" and password
    | reset options for your application. You may change these defaults
    | as required, but they're a perfect start for most applications.
    |
    */

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

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    |
    | Next, you may define every authentication guard for your application.
    | Of course, a great default configuration has been defined for you
    | here which uses session storage and the Eloquent user provider.
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | Supported: "session", "token"
    |
    */

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

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],
        'administrators' => [
            'driver' => 'session',
            'provider' => 'administrators',
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | If you have multiple user tables or models you may configure multiple
    | sources which represent each model / table. These sources may then
    | be assigned to any extra authentication guards you have defined.
    |
    | Supported: "database", "eloquent"
    |
    */

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],
        'administrators' => [
            'driver' => 'eloquent',
            'model' => App\Models\Administrator::class,
        ]
        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    |
    | You may specify multiple password reset configurations if you have more
    | than one user table or model in the application and you want to have
    | separate password reset settings based on the specific user types.
    |
    | The expire time is the number of minutes that the reset token should be
    | considered valid. This security feature keeps tokens short-lived so
    | they have less time to be guessed. You may change this as needed.
    |
    */

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
            'throttle' => 60,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Password Confirmation Timeout
    |--------------------------------------------------------------------------
    |
    | Here you may define the amount of seconds before a password confirmation
    | times out and the user is prompted to re-enter their password via the
    | confirmation screen. By default, the timeout lasts for three hours.
    |
    */

    'password_timeout' => 10800,

];
login.blade.php
<html>
<head>
    <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
    <form method="POST" action="multi_login">
        @csrf
        <div class="p-3">
            @error('auth')
            <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-3">
                &#x26A0; {{ $message }}
            </div>
            @enderror
            <label class="block">メールアドレス</label>
            <input class="border rounded mb-3 px-2 py-1" type="text" name="email">
            <label class="block">パスワード</label>
            <input class="border rounded mb-3 px-2 py-1" type="password" name="password">
            <label class="block">ユーザータイプ</label>
            <select name="guard" class="border rounded px-2 py-1 mb-5">
                <option value="">▼選択してください</option>
                <option value="administrators">管理者</option>
            </select>
            <br>
            <button class="bg-blue-500 text-white rounded px-3 py-2" type="submit">ログイン</button>
        </div>
    </form>
</body>
</html>

認証関連のルーティング情報はこちらです

web.php
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\HelloController;
use App\Http\Middleware\HelloMiddleware;
use App\Http\Controllers\PersonController;
use App\Http\Controllers\PurchasehistoryController;
use App\Http\Controllers\BoardController;
use App\Http\Controllers\RestappController;
use App\Http\Controllers\ProductController;
use App\Http\Controllers\StoreController;
use App\Http\Controllers\CartController;
use App\Http\Controllers\MultiAuthController;
use App\Http\Controllers\ShopController;
use Illuminate\Support\Facades\Mail;
use App\Mail\Thanks;

Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard', function () {
    return view('dashboard');
})->name('dashboard');



Route::get('multi_login', [MultiAuthController::class, 'showLoginForm']);
Route::post('multi_login', [MultiAuthController::class, 'login']);

// ログアウト
Route::get('multi_login/logout', [MultiAuthController::class, 'logout']);

// ログイン後のページ
Route::prefix('administrators')->middleware('auth:administrators')->group(function(){

Route::get('dashboard', function(){ return '管理者でログイン完了'; });
Route::get('home', [MultiAuthController::class, 'index']);
});

データベースはこちらです。
administrators

スクリーンショット 2021-10-20 13.40.15.png

administrators/homeに行くとログインせずにOKが出てしまいます。

追加
Controllerをいじるとうまくいきましたが、1つのエラーが出ました。

MultiAuthController.php
<?php
namespace App\Http\Controllers;

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

class MultiAuthController extends Controller
{
    public function showLoginForm() {

        return view('multi_auth.login');

    }
    public function index() {

        return 'OK';

    }

    public function login(Request $request) {

        $credentials = $request->only(['email', 'password']);
        $guard = $request->guard;

        if(Auth::guard($guard)->attempt($credentials)) {

            return redirect($guard .'/dashboard'); // ログインしたらリダイレクト

        }

        return back()->withErrors([
            'auth' => ['認証に失敗しました']
        ]);
    }
}

エラーが出ました。

Undefined method 'attempt'.

attemptはうまく動いてないようです?

0

1Answer

Comments

  1. @TKngDisuke

    Questioner

    わかりました
    更新しましたので確認お願いします
  2. @TKngDisuke

    Questioner

    Controllerのエラーでこのようなメッセージが表示されていました
    Undefined type 'Auth'
    Authの所でエラーが出ているのですが、何かAuthに関するものを上に入れた方がいいんですかね
  3. @TKngDisuke

    Questioner

    use Illuminate\Support\Facades\Auth;
    を追加するとエラーは無くなりましたが、なぜかエラーが2つ出てしまいます。
    エラー内容を更新しました
  4. Undefined method 'attempt'.はエディターのエラーですか?
    そうであれば、laravel-ide-helperをインストールすれば消えます。

    エディターのエラーを無視して実行してみましたか?
  5. @TKngDisuke

    Questioner

    エディターのエラーです。
    インストールしても消えずにエディターのエラーが出ます。
    Undefined method 'attempt'.
    エラーを無視して実行してもログイン認証(管理者)がされません。
    管理者ではない普通のUserを選択すると認証されます。
    コントローラーのifの部分を if($guard= "administrators") {

    return redirect($guard .'/home'); // ログインしたらリダイレクト

    }にするとhomeにリダイレクトできました。
    Userの認証をするとhomeに行くことができましたのでattemptnの挙動は正しく、adminのパスワード認証などに問題があることがわかりました。

    Userのデータベースを見たところ、パスワードが文字化け(?)かしており、暗号に変換されているのでは無いかということでそのデータベースのパスワードをコピーしてAdmin Userのパスワードに貼り付けをしてログインしようとするとうまくいきました。
    データベースの中で無理やりUserのデータを作ることはしない方が良いのかもしれません。

    2つ目の強制リダイレクトができない現象を解決したいです。
    今思ったのですが、ログアウト機能を要していないのでもしかしたらずっとログインしている状態だからリダイレクトが行われていないのかと気づきました、、
  6. `$guard`をログにプリントして確認しましたか?
  7. @TKngDisuke

    Questioner

    確認したところ、ログインしたままのようです。
    解決しました。ありがとうございました。

Your answer might help someone💌