laravel breeze Multi Auth - Admin Guard с двумя разными регистрациями

Я использую laravel breeze в качестве пакета scaffolding для аутентификации. Я хочу создать множественную аутентификацию с использованием защиты laravel для двух разных форм регистрации для двух типов пользователей (Admin, User) .

Основная идея того, чего я хочу достичь:

У меня есть две таблицы в базе данных: одна для администраторов, а другая - для пользователей, чего я хочу добиться, так это если администраторы решат зарегистрировать учетную запись в качестве администратора, она отобразит форму регистрации с указанными полями для администратора. после этого я хочу проверить, вошел ли пользователь в систему как администратор или пользователь, если он вошел в систему как администратор, перенаправит его / ее на указанную панель инструментов, созданную только для администраторов.

Он отлично работает для регистрации, но не может войти в систему как администратор, вот простое объяснение того, чего я хочу достичь:

приложение \ Models \ Admin.php

      <?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class Admin extends Authenticatable
{
    use HasFactory, Notifiable;
    protected $table = 'admins';
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

config \ auth.php

      <?php

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

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

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

        // Admin guards
        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],

        'admin-api' => [
            'driver' => 'token',
            'provider' => 'admins',
        ],
    ],

    
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],

        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Models\Admin::class,
        ],
    ],

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

        'admins' => [
            'provider' => 'admins',
            'table' => 'password_resets',
            'expire' => 60,
            'throttle' => 60,
        ],
    ],
    
    'password_timeout' => 10800,

];

приложение \Http\ Middleware \RedirectIfAuthenticated.php

      <?php

namespace App\Http\Middleware;

use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class RedirectIfAuthenticated
{
    public function handle(Request $request, Closure $next, ...$guards)
    {
        $guards = empty($guards) ? [null] : $guards;
        // dd($guards);
        foreach ($guards as $guard) {
            switch ($guard) {
                case 'admin':
                    if (Auth::guard($guard)->check()) {
                        return redirect()->route('admin.dashboard');
                    }
                    break;

                default:
                    if (Auth::guard($guard)->check()) {
                        return redirect('/dashboard');
                    }
                    break;
            }
        }

        return $next($request);
    }
}

routes\web.php

      <?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Admin\RegisteredUserController;
use App\Http\Controllers\Admin\AuthenticatedSessionController;

Route::get('/', function () {
    return view('welcome');
});

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

require __DIR__ . '/auth.php';

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

Route::get('/admin-register', [RegisteredUserController::class, 'create'])
    ->middleware('guest:admin')
    ->name('admin.register');

Route::post('/admin-register', [RegisteredUserController::class, 'store'])
    ->middleware('guest:admin');

Route::get('/admin-login', [AuthenticatedSessionController::class, 'create'])
    ->middleware('guest:admin')
    ->name('admin.login');

Route::post('/admin-login', [AuthenticatedSessionController::class, 'store'])
    ->middleware('guest:admin');
Route::post('/admin-logout', [AuthenticatedSessionController::class, 'destroy'])
    ->name('admin.logout')
    ->middleware('auth:admin');

приложение \Http\ Controllers \ Admin\ AuthenticatedSessionController.php

      namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\LoginRequest;
use App\Providers\RouteServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

    class AuthenticatedSessionController extends Controller
    {
        public function create()
        {
            return view('admin.login');
        }
    
           public function store(LoginRequest $request)
        {
            $request->authenticate();
    
            $request->session()->regenerate();
    
            return redirect('admin/dashboard');
        }
    
        public function destroy(Request $request)
        {
            Auth::logout();
    
            $request->session()->invalidate();
    
            $request->session()->regenerateToken();
    
            return redirect('/');
        }
    }

приложение \Http\ Controllers \ Admin\ RegisteredUserController.php

      <?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Admin;
use App\Providers\RouteServiceProvider;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;

class RegisteredUserController extends Controller
{
    public function create()
    {
        return view('admin.register');
    }

    public function store(Request $request)
    {
        $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|confirmed|min:8',
        ]);

        Auth::login($user = Admin::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]));

        event(new Registered($user));

        return redirect('admin/dashboard');
    }
}

приложение \Http\ Requests \ Admin\ LoginRequest.php

      <?php

namespace App\Http\Requests\Admin;

use Illuminate\Auth\Events\Lockout;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

class LoginRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'email' => 'required|string|email',
            'password' => 'required|string',
        ];
    }

    public function authenticate()
    {
        $this->ensureIsNotRateLimited();

        if (! Auth::attempt($this->only('email', 'password'), $this->filled('remember'))) {
            RateLimiter::hit($this->throttleKey());

            throw ValidationException::withMessages([
                'email' => __('auth.failed'),
            ]);
        }

        RateLimiter::clear($this->throttleKey());
    }

    public function ensureIsNotRateLimited()
    {
        if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
            return;
        }

        event(new Lockout($this));

        $seconds = RateLimiter::availableIn($this->throttleKey());

        throw ValidationException::withMessages([
            'email' => trans('auth.throttle', [
                'seconds' => $seconds,
                'minutes' => ceil($seconds / 60),
            ]),
        ]);
    }

    public function throttleKey()
    {
        return Str::lower($this->input('email')).'|'.$this->ip();
    }
}

2 ответа

Решение

После трех дней усилий я сам нашел решение.

В функции authenticate()в приложении \Http\Requests\Admin\LoginRequest.php. Я заменил Auth::attempt(...) к Auth::guard('admin')->attempt(...)

      public function authenticate()
{
    $this->ensureIsNotRateLimited();

    if (! Auth::guard('admin')->attempt($this->only('email', 'password'), $this->filled('remember'))) {
        RateLimiter::hit($this->throttleKey());

        throw ValidationException::withMessages([
            'email' => __('auth.failed'),
        ]);
    }

    RateLimiter::clear($this->throttleKey());
}

Теперь он отлично работает для входа в систему и регистрации администратора

Хорошо, мой проект немного отличается и не дает 100% ответа, но я решил оставить их здесь, это может кому-то помочь.

приложение / Http / Requests / Auth / LoginRequest.php

      public function authenticate()
{
    $this->ensureIsNotRateLimited();

    if (!Auth::attempt($this->only('email', 'password'), $this->filled('remember')) ||
        !auth()->user()->isAdmin()      <------------ added
    ) {
        Auth::logout();                 <------------ added
        RateLimiter::hit($this->throttleKey());

        throw ValidationException::withMessages([
            'email' => __('auth.failed'),
        ]);
    }

    RateLimiter::clear($this->throttleKey());
}

Я добавил функцию isAdmin в модель пользователя, она не встроена заранее

Другие вопросы по тегам