Laravel перенаправить обратно в исходное место после входа в систему

189

Это похоже на довольно простой поток и Laravelимеет так много хороших решений для базовых вещей, я чувствую, что что-то упустил.

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

Есть ли хороший способ узнать, на какую страницу они пытались попасть изначально? Так как Laravel - это тот, кто перехватывает запрос, я не знал, отслеживает ли он где-нибудь для легкой маршрутизации после входа пользователя в систему.

Если нет, мне было бы интересно услышать, как некоторые из вас реализовали это вручную.

JOV
источник

Ответы:

234

Для Laravel 5.3 и выше

Проверьте ответ Скотта ниже.

Для Laravel 5 до 5,2

Проще говоря,

На промежуточном ПО аутентификации:

// redirect the user to "/login"
// and stores the url being accessed on session
if (Auth::guest()) {
    return redirect()->guest('login');
}
return $next($request);

При входе в систему:

// redirect the user back to the intended page
// or defaultpage if there isn't one
if (Auth::attempt(['email' => $email, 'password' => $password])) {
    return redirect()->intended('defaultpage');
}

Для Laravel 4 (старый ответ)

На момент этого ответа не было официальной поддержки со стороны самой структуры. В настоящее время вы можете использоватьметод, указанный bgdrl нижеэтот метод: (Я пытался обновить его ответ, но, похоже, он не примет)

На фильтр авторизации:

// redirect the user to "/login"
// and stores the url being accessed on session
Route::filter('auth', function() {
    if (Auth::guest()) {
        return Redirect::guest('login');
    }
});

При входе в систему:

// redirect the user back to the intended page
// or defaultpage if there isn't one
if (Auth::attempt(['email' => $email, 'password' => $password])) {
    return Redirect::intended('defaultpage');
}

Для Laravel 3 (даже более старый ответ)

Вы можете реализовать это так:

Route::filter('auth', function() {
    // If there's no user authenticated session
    if (Auth::guest()) {
        // Stores current url on session and redirect to login page
        Session::put('redirect', URL::full());
        return Redirect::to('/login');
    }
    if ($redirect = Session::get('redirect')) {
        Session::forget('redirect');
        return Redirect::to($redirect);
    }
});
// on controller
public function get_login()
{
    $this->layout->nest('content', 'auth.login'); 
}

public function post_login()
{
    $credentials = [
        'username' => Input::get('email'),
        'password' => Input::get('password')
    ];

    if (Auth::attempt($credentials)) {
        return Redirect::to('logged_in_homepage_here');
    }

    return Redirect::to('login')->with_input();
}

Сохранение перенаправления в сеансе имеет преимущество сохранения его, даже если пользователь пропустил ввод своих учетных данных или у него нет учетной записи и он должен зарегистрироваться.

Это также позволяет чему-либо еще, кроме Auth, устанавливать перенаправление на сеанс, и это будет работать магическим образом.

vFragosop
источник
Не будет ли больше смысла мелькать на сессии, а не ставить и забывать? Ваше действие при входе в систему просто вернет перенаправление к значению в сеансе, если оно существует, или к странице по умолчанию в противном случае.
Билалк
2
Я отредактировал ответ, чтобы объяснить, почему это лучше, чем flash.
vFragosop
В этом есть смысл. Лучше, чем перепрошивать каждый раз.
Билалк
1
Когда Auth :: try () проходит, вы можете просто перенаправить пользователя на страницу по умолчанию (обычно на его домашнюю страницу). Это перенаправление снова пройдет через этот фильтр и перенаправит его на исходный запрошенный URL, если он есть. Иначе он просто продолжит рендеринг своего дома. Я приведу пример действия входа в систему.
vFragosop
1
в 5.1 он находится в промежуточном программном обеспечении RedirectIfAuthenticated.php: if ($ this-> auth-> check ()) {return redirect ('/ privatepage'); }
Дэйв Дрисманс
73

Laravel> = 5.3

Изменения Auth в 5.3 делают его реализацию немного проще и немного отличаются от 5.2, поскольку промежуточное программное обеспечение Auth было перемещено в сервисный контейнер.

Изменить новый перенаправитель авторизации Middleware

/app/Http/Middleware/RedirectIfAuthenticated.php

Немного измените функцию дескриптора, чтобы она выглядела следующим образом:

public function handle($request, Closure $next, $guard = null)
{
    if (Auth::guard($guard)->check()) {
        return redirect()->intended('/home');
    }

    return $next($request);
}

TL; DR объяснение

Единственная разница в 4-й строке; по умолчанию это выглядит так:

return redirect("/home");

Поскольку Laravel> = 5.3 автоматически сохраняет последний «намеченный» маршрут при проверке Auth Guard, он изменяется на:

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

Это говорит Laravel перенаправить на последнюю намеченную страницу перед входом в систему, в противном случае перейдите в «/ home» или куда вы хотите отправить их по умолчанию.

Надеюсь, что это поможет кому-то еще - не так много различий между 5.2 и 5.3, и в этой области, в частности, немало.

Скотт Байерс
источник
2
для Laravel 6.4 это больше не работает ... есть идеи?
Алекс Toader
Я бы использовал, return redirect()->intended(RouteServiceProvider::HOME);чтобы сохранить ваш домашний путь в одном месте.
Матеуш
26

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

Redirect::guest();
Redirect::intended();

Вы можете применить этот фильтр к маршрутам, которые требуют аутентификации.

Route::filter('auth', function()
{
    if (Auth::guest()) {
           return Redirect::guest('login');
    }
});

Этот метод в основном делает для хранения страницы, которую вы пытались посетить, и он перенаправляет вас на страницу входа .

Когда пользователь аутентифицирован, вы можете позвонить

return Redirect::intended();

и он перенаправляет вас на страницу, которую вы пытались открыть вначале.

Это отличный способ сделать это, хотя я обычно использую метод ниже.

Redirect::back()

Вы можете проверить этот удивительный блог.

Яннис Кристофакис
источник
Это намного лучше, чем решения выше. Приведенные выше решения требуют возможности передать закрытие функции входа в систему, чего я не мог сделать с 4.1. Но это было намного проще и работало как есть.
user2662680
20

Вы можете использовать функцию Redirect:. Он перенаправит пользователя на URL-адрес, к которому он пытался получить доступ, прежде чем его перехватит фильтр аутентификации. Этому методу может быть предоставлен резервный URI, если предполагаемое назначение недоступно.

В посте логин / регистрация:

return Redirect::intended('defaultpageafterlogin');
dabuno
источник
11

Я использовал это некоторое время на моем коде выбора языка. Пока вам нужно вернуться только на 1 страницу, она работает нормально:

return Redirect::to(URL::previous());

Это не самое мощное решение, но оно очень простое и может помочь решить несколько головоломок. :)

Федерико Станго
источник
5
Да предыдущая () работает отлично. Но если ваша первая попытка входа не удалась (так что страница «сбой входа в систему» ​​стала вашей предыдущей страницей), а вторая попытка входа прошла успешно, вы снова будете перенаправлены на страницу входа (которая может перенаправить вас на домашнюю страницу).
Шриганеш Синтре
11

Измените конструктор LoginControllers на:

public function __construct()
    {
        session(['url.intended' => url()->previous()]);
        $this->redirectTo = session()->get('url.intended');

        $this->middleware('guest')->except('logout');
    }

Он перенаправит вас обратно на страницу ДО страницы входа (2 страницы назад).

MevlütÖzdemir
источник
Единственный, который работает для меня. Это должно означать, что у меня где-то еще происходит перенаправление, но кто знает, где.
Артур Тарасов
8
return Redirect::intended('/');

это перенаправит вас на страницу по умолчанию вашего проекта, т.е. на стартовую страницу.

Параг Бингре
источник
6

Для Laravel 5. * попробуйте это.

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

или

return Redirect::intended('/');
Нуруззаман Милон
источник
5

Ларавел 3

Я немного подправил твой код (Vinícius Fragoso Pinheiro) и поместил следующее в filters.php

Route::filter('auth', function()
{
    // If there's no user authenticated session
    if (Auth::guest()) {
        // Flash current url to session and redirect to login page
        Session::flash('redirect', URL::full());
        return Redirect::guest('login');
    }
});

А затем в моем AuthController.php:

// Try to log the user in.
if (Auth::attempt($userdata)) {

    if ($redirect = Session::get('redirect')) {
        return Redirect::to($redirect);
    } else {
        // Redirect to homepage
        return Redirect::to('your_default_logged_in_page')->with('success', 'You have logged in successfully');
    }
} else {
    // Reflash the session data in case we are in the middle of a redirect 
    Session::reflash('redirect');

    // Redirect to the login page.
    return Redirect::to('login')->withErrors(['password' => 'Password invalid'])->withInput(Input::except('password'));
}

Обратите внимание, что 'redirect'данные сеанса перепрошиваются, если есть проблема аутентификации. Это сохраняет перенаправление без изменений во время любых неудачных попыток входа в систему, но если пользователь щелкнет в любой момент, следующий процесс входа не будет прерван данными сеанса.

Вам также необходимо перепрошить данные в момент отображения формы входа в систему, в AuthControllerпротивном случае цепочка разорвана:

public function showLogin()
{
    // Reflash the session data in case we are in the middle of a redirect 
    Session::reflash('redirect');

    // Show the login page
    return View::make('auth/login');
}
Джо Ричардс
источник
3

использование Redirect;

Тогда используйте это:

return Redirect::back();
Уджвал Дхакал
источник
0

Larvel 5.3 это на самом деле работает для меня, просто обновив LoginController.php

 use Illuminate\Support\Facades\Session;
 use Illuminate\Support\Facades\URL;


public function __construct()
{
    $this->middleware('guest', ['except' => 'logout']);
    Session::set('backUrl', URL::previous());
}


public function redirectTo()
{
    return Session::get('backUrl') ? Session::get('backUrl') :   $this->redirectTo;
}

ссылка: https://laracasts.com/discuss/channels/laravel/redirect-to-previous-page-after-login

Номи
источник
0

Для Laravel 5.5 и, вероятно, 5.4

В App \ Http \ Middleware \ RedirectIfAuthenticated измените redirect('/home')на redirect()->intended('/home')в функции дескриптора:

public function handle($request, Closure $next, $guard = null)
{
    if (Auth::guard($guard)->check()) {
        return redirect()->intended('/home');
    }

    return $next($request);
}

в App \ Http \ Controllers \ Auth \ LoginController создайте showLoginForm()функцию следующим образом:

public function showLoginForm()
{
    if(!session()->has('url.intended'))
    {
        session(['url.intended' => url()->previous()]);
    }
    return view('auth.login');
}

Таким образом, если было намерение для другой страницы, он будет перенаправлять туда, иначе он будет перенаправлять домой.

DerDare
источник
0

Я использую следующий подход с пользовательским контроллером входа и промежуточным программным обеспечением для Laravel 5.7, но я надеюсь, что это работает в любой из версий laravel 5

  • в промежуточном программном обеспечении

    if (Auth::check()){
        return $next($request);
    }
    else{
      return redirect()->guest(route('login'));
    }
  • метод входа внутри контроллера

    if (Auth::attempt(['email' => $email, 'password' => $password])) {
    return redirect()->intended('/default');
    }
  • Если вам нужно передать намеренный URL-адрес на стороне клиента , вы можете попробовать следующее

       if (Auth::attempt(['username' => $request->username, 'password' => $request->password])) {
           $intended_url= redirect()->intended('/default')->getTargetUrl();
           $response = array(
          'status' => 'success',
          'redirectUrl' => $intended_url,
          'message' => 'Login successful.you will be redirected to home..', );
          return response()->json($response);
        } else {
            $response = array(
          'status' => 'failed',
          'message' => 'username or password is incorrect', );
         return response()->json($response);
        }
Найим Азад
источник
0

Во-первых, вы должны знать, как вы перенаправляете пользователя на маршрут входа в систему:

return redirect()->guest('/signin');

Не так:

return redirect()->intended('/signin');
Одилов Ойбек
источник
0

Laravel теперь поддерживает эту функцию "из коробки"! (Я верю с 5.5 или ранее).

Добавьте __construct()метод к себе, Controllerкак показано ниже:

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

После входа ваши пользователи будут перенаправлены на страницу, которую они изначально хотели посетить.

Вы также можете добавить функцию проверки электронной почты Laravel, как того требует логика вашего приложения:

public function __construct()
{
    $this->middleware(['auth', 'verified']);
}

Документация содержит очень краткий пример:

Также можно выбрать методы контроллера, к которым применяется промежуточное программное обеспечение, с помощью except или onlyпараметров.

Пример с except:

public function __construct()
{
    $this->middleware('auth', ['except' => ['index', 'show']]);
}

Пример с only:

public function __construct()
{
    $this->middleware('auth', ['only' => ['index', 'show']]);
}

Больше информации exceptи onlyопций промежуточного программного обеспечения:

LobsterBaz
источник
0

Если вы используете Axios или другую библиотеку JavaScript AJAX, вы можете получить URL-адрес и перейти к интерфейсу

Вы можете сделать это с помощью кода ниже

   $default = '/';

   $location = $request->session()->pull('url.intended', $default);

    return ['status' => 200, 'location' => $location];

Это вернет строку в формате json

Эммануэль Давид
источник
0

В Ларавеле 5,8

в App \ Http \ Controllers \ Auth \ LoginController добавьте следующий метод

public function showLoginForm()
{
    if(!session()->has('url.intended'))
        {
            session(['url.intended' => url()->previous()]);
        }
    return view('auth.login');
}

в App \ Http \ Middleware \ RedirectIfAuthenticated замените «возвратный редирект ('/ home');» следующим

 if (Auth::guard($guard)->check()) 
    {
        return redirect()->intended();
    }
Ян Бойонго
источник
-1

Вы пробовали это в вашем rout.php?

Route::group(['middleware' => ['web']], function () {
    //
    Route::get('/','HomeController@index');
});
Arios
источник
-1
       // Also place this code into base controller in contract function,            because ever controller extends base  controller
 if(Auth::id) {
  //here redirect your code or function
 }
if (Auth::guest()) {
       return Redirect::guest('login');
}
крутой программист
источник
2
Пожалуйста, предоставьте некоторые комментарии, чтобы сопровождать ваш код, чтобы обеспечить некоторый контекст. Спасибо
Suever
-1

Вот мое решение для 5.1. Мне нужно было, чтобы кто-то нажал кнопку «Мне нравится» в сообщении, перенаправился на страницу входа и вернулся на исходную страницу. Если они уже вошли в систему, hrefкнопка «Мне нравится» была перехвачена с помощью JavaScript и превращена в запрос AJAX.

Кнопка что-то вроде <a href="https://stackoverflow.com/like/931">Like This Post!</a>. /like/931обрабатывается LikeController, который требует authпромежуточного программного обеспечения.

В промежуточном программном обеспечении Authenticate ( handle()функция) добавьте что-то вроде этого в начале:

    if(!str_contains($request->session()->previousUrl(), "/auth/login")) {
        $request->session()->put('redirectURL', $request->session()->previousUrl());
        $request->session()->save();
    }

Измените /auth/loginлюбой URL-адрес для входа в систему. Этот код сохраняет URL-адрес исходной страницы в сеансе, если только URL-адрес не является URL-адресом для входа. Это необходимо, потому что кажется, что это промежуточное программное обеспечение вызывается дважды. Я не уверен, почему или если это правда. Но если вы не проверяете это условие, оно будет равно правильной исходной странице, а затем как-то получится /auth/login. Вероятно, есть более элегантный способ сделать это.

Затем в LikeControllerконтроллере или в любом другом имеющемся контроллере, который обрабатывает URL для кнопки, нажатой на исходной странице:

//some code here that adds a like to the database
//...
return redirect($request->session()->get('redirectURL'));

Этот метод очень прост, не требует переопределения существующих функций и отлично работает. Возможно, для Ларавела есть более простой способ сделать это, но я не уверен, что это такое. Использование intended()функции не работает в моем случае, потому что LikeController нужно было также знать, какой предыдущий URL был перенаправлен обратно на него. По существу два уровня перенаправления назад.

Бринн Бейтман
источник
-1

Для Laravel 5.2 (предыдущие версии я не использовал)

Вставьте код в файл app \ Http \ Controllers \ Auth \ AurhController.php

   /**
 * Overrides method in class 'AuthenticatesUsers'
 *
 * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
 */
public function showLoginForm()
{
    $view = property_exists($this, 'loginView')
        ? $this->loginView : 'auth.authenticate';
    if (view()->exists($view)) {
        return view($view);
    }
    /**
     * seve the previous page in the session
     */
    $previous_url = Session::get('_previous.url');
    $ref = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
    $ref = rtrim($ref, '/');
    if ($previous_url != url('login')) {
        Session::put('referrer', $ref);
        if ($previous_url == $ref) {
            Session::put('url.intended', $ref);
        }
    }
    /**
     * seve the previous page in the session
     * end
     */
    return view('auth.login');
}
/**
 * Overrides method in class 'AuthenticatesUsers'
 *
 * @param Request $request
 * @param $throttles
 *
 * @return \Illuminate\Http\RedirectResponse
 */
protected function handleUserWasAuthenticated(Request $request, $throttles)
{
    if ($throttles) {
        $this->clearLoginAttempts($request);
    }
    if (method_exists($this, 'authenticated')) {
        return $this->authenticated($request, Auth::guard($this->getGuard())->user());
    }
    /*return to the previous page*/
    return redirect()->intended(Session::pull('referrer'));
    /*return redirect()->intended($this->redirectPath()); /*Larevel default*/
}

И импортировать пространство имен: use Session;

Если вы не внесли никаких изменений в файл app \ Http \ Controllers \ Auth \ AurhController.php, вы можете просто заменить его файлом из GitHub.

Здорово
источник
-1

Laravel 5.2

Если вы используете другое промежуточное ПО, такое как промежуточное ПО администратора, вы можете установить сеанс для url.intended , используя следующее:

В основном нам нужно установить вручную \Session::put('url.intended', \URL::full());для перенаправления.

пример

  if (\Auth::guard($guard)->guest()) {
      if ($request->ajax() || $request->wantsJson()) {
         return response('Unauthorized.', 401);
      } else {
        \Session::put('url.intended', \URL::full());
        return redirect('login');
      }
  }

При попытке входа

Убедитесь, что при входе в систему используется return \Redirect::intended('default_path');

Рашедул Ислам Сагор
источник
Вот для чего redirect()->guest('login').
Эмиль Бержерон
-1

Для Laravle 5.7 Вам необходимо внести изменения в:

Промежуточное> RedirectIfAuthenticated.php

Изменить это:

public function handle($request, Closure $next, $guard = null)
    {
        if (Auth::guard($guard)->check()) {
            return redirect('/admin');
        }

        return $next($request);
    }

К этому:

public function handle($request, Closure $next, $guard = null)
    {
        if (Auth::guard($guard)->check()) {
            return redirect('/yourpath');
        }

        return $next($request);
    }

возвратный редирект ('/ yourpath');

Принц Ахмед
источник
Что такое mypath? (пользователь передает обратно к этому)
Мостафа Норзаде