Laravel - проблема перенаправления без аутентификации с множественной аутентификацией

У меня установлена ​​система множественной аутентификации в Laravel 5.7.

На сайте есть раздел «администратор» и раздел «учащийся». Когда вы пытаетесь получить доступ к части любого сайта, он перенаправляет вас на правильную страницу входа, если вы еще не вошли в систему.

Однако, если выполнить следующие действия, я столкнусь с проблемой перенаправления:

  1. Я пытаюсь получить доступ к части (не к логину) сайта «администратора», который перенаправляет меня на логин администратора.
  2. Затем, если я напрямую свяжусь с разделом входа на странице «учащийся» и войду в систему, вместо перехода на домашнюю страницу он перенаправит меня обратно к логину администратора.

Он правильно выполняет вход в систему, но неправильно перенаправляет на другую страницу входа. Проблема также возникает и наоборот, если я получаю автоматическое перенаправление на «учащегося», затем ссылаюсь непосредственно на страницу входа администратора и авторизуюсь.

Я считаю, что сузил проблему до неаутентифицированной функции, которую я поместил в файл Exception / Handler.php, но я не могу понять, куда дальше идти.

protected function unauthenticated($request, AuthenticationException $exception)
    {
        if ($request->expectsJson()) {
            return response()->json(['error' => 'Unauthenticated.'], 401);
        }
        $guard = array_get($exception->guards(), 0);
        switch ($guard) {
            case 'learner':
                $login = 'learner.login';
                break;
            default:
                $login = 'login';
                break;
        }
        return redirect()->guest(route($login));
    }

Использование каждой отдельной страницы входа в систему работает нормально. Когда вы следуете описанному выше процессу, я вижу проблемы.

Я использую отдельное промежуточное ПО в каждом контроллере, например:

Домашний контроллер администратора

public function __construct()
    {
        $this->middleware('auth');
    }

Контроллер входа в систему администратора:

public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }

Домашний контроллер ученика

public function __construct()
    {
        $this->middleware('auth:learner');

    }

Контроллер входа в систему для учащихся:

public function __construct()
    {
        $this->middleware('guest:learner')->except('logout');
    }

Решение: очистить предполагаемый URL-адрес с помощью Session: Forgot ('url.intended');

protected function unauthenticated($request, AuthenticationException $exception)
    {
        // dd($exception);
        if ($request->expectsJson()) {
            return response()->json(['error' => 'Unauthenticated.'], 401);
        }
        $guard = array_get($exception->guards(), 0);
        switch ($guard) {
            case 'learner':
                $login = 'learner.login';
                break;
            default:
                $login = 'login';
                break;
        }
        Session::forget('url.intented'); 
        return redirect()->route($login);
    }

person knat    schedule 20.09.2018    source источник
comment
Используете ли вы отдельные промежуточное ПО для защиты маршрутов или одно и то же промежуточное ПО?   -  person Azeame    schedule 20.09.2018
comment
Я использую отдельное промежуточное ПО в каждом контроллере через __construct. Я обновлю свой основной пост, как они выглядят.   -  person knat    schedule 20.09.2018


Ответы (2)


Решение: очистить предполагаемый URL-адрес с помощью Session: Forgot ('url.intended');

protected function unauthenticated($request, AuthenticationException $exception)
    {
        // dd($exception);
        if ($request->expectsJson()) {
            return response()->json(['error' => 'Unauthenticated.'], 401);
        }
        $guard = array_get($exception->guards(), 0);
        switch ($guard) {
            case 'learner':
                $login = 'learner.login';
                break;
            default:
                $login = 'login';
                break;
        }
        Session::forget('url.intented'); 
        return redirect()->route($login);
    }
person knat    schedule 21.09.2018

Вот пример того, что я использую в производственной среде для приложения, имеющего два пользовательских класса, которые должны быть зарегистрированы для доступа к своим отдельным ресурсам. Класс User использует аутентификацию Laravel по умолчанию без изменений, однако пользователи моего класса Admin используют это настраиваемое промежуточное ПО:

<?php

namespace App\Http\Middleware;

use App\Admin;
use Closure;
use Illuminate\Support\Facades\Auth;

class AdminMiddleware
{

    public function handle($request, Closure $next)
    {
        if (Auth::guest()) {
            return redirect(route('admin.login'));
        }

        if (!$request->user() instanceof Admin) {
            return redirect(route('restricted'));
        }
        return $next($request);
    }
}

Я зарегистрировал AdminMiddleware в app/Http/Kernel.php вот так:

protected $routeMiddleware = [
    'admin' => \App\Http\Middleware\AdminMiddleware::class,

    /*** OTHER MIDDLEWARES ARE HERE ***/
];

В файле routes/web.php я обернул маршруты так:

Route::group(['prefix' => 'admin', 'as' => 'admin.', 'middleware' => 'auth:admin'], function () {
    /**** ADMIN ROUTES ARE HERE ****/
});

Route::group(['middleware' => 'auth'], function () {
    /**** CLIENT ROUTES ARE HERE ****/
});

И у меня есть собственный AdminLoginController, который перезаписывает переменную пути $redirect, а также функции guard(), showLoginForm() и redirectTo() и выглядит так:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\Auth;

class AdminLoginController extends Controller
{

    use AuthenticatesUsers;

    protected $redirectTo = '/admin/home';

    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    } 

    public function guard()
    {
        return Auth::guard('admin');
    }

    public function showLoginForm()
    {
        return view('auth.admin.login');
    }

    public function redirectTo()
    {
        return route('admin.home');
    }

}

Наконец, в config/auth.php у меня есть следующие ссылки на охранников, провайдеров и пароли:

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

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

    'admin' => [
        'driver' => 'session',
        'provider' => 'admins',
    ],

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


'providers' => [

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

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

],

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

Конечно, это означает, что мои администраторы и пользователи хранятся в отдельных таблицах в базе данных, но это работает очень хорошо, без каких-либо проблем, так что меня это вполне устраивает.

person Azeame    schedule 20.09.2018
comment
Где / как вы зарегистрировали AdminMiddleware? Кажется, я не могу заставить свою работать должным образом. - person knat; 21.09.2018
comment
Извините, я пропустил это раньше, я просто добавил его как второй блок кода - person Azeame; 21.09.2018
comment
Спасибо. Итак, где вы на самом деле называете промежуточное ПО («админ»)? Похоже, что единственное промежуточное ПО, которое вы используете для маршрутов администратора, это auth: admin. - person knat; 21.09.2018
comment
Правильно, я ссылаюсь только на auth:admin в файле маршрута, но вы также можете вызвать его в методе Controller __construct. - person Azeame; 21.09.2018
comment
А пока нашел собственное решение! Добавление этого в конец функции-обработчика очищает маршруты с отступом и предотвращает неправильное перенаправление. Сессия :: забыть ('url.intented'); return redirect () - ›route ($ login); - person knat; 21.09.2018