Laravel redirige de nuevo al destino original después de iniciar sesión

189

Esto parece un flujo bastante básico, y Laraveltiene tantas buenas soluciones para cosas básicas, siento que me falta algo.

Un usuario hace clic en un enlace que requiere autenticación. El filtro de autenticación de Laravel se activa y los dirige a una página de inicio de sesión. El usuario inicia sesión, luego va a la página original a la que intentaban acceder antes de que se activara el filtro 'auth'.

¿Hay una buena manera de saber a qué página intentaban llegar originalmente? Como Laravel es quien intercepta la solicitud, no sabía si realiza un seguimiento en algún lugar para facilitar el enrutamiento después de que el usuario inicie sesión.

Si no, me gustaría saber cómo algunos de ustedes han implementado esto manualmente.

JOV
fuente

Respuestas:

234

Para Laravel 5.3 y superior

Verifique la respuesta de Scott a continuación.

Para Laravel 5 hasta 5.2

Simplemente pon,

En el middleware de autenticación:

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

En la acción de inicio de sesión:

// 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');
}

Para Laravel 4 (respuesta anterior)

En el momento de esta respuesta no había soporte oficial del marco en sí. Hoy en día puedes usarel método señalado por bgdrl a continuacióneste método: (he intentado actualizar su respuesta, pero parece que no aceptará)

En filtro de autenticación:

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

En la acción de inicio de sesión:

// 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');
}

Para Laravel 3 (respuesta incluso anterior)

Podrías implementarlo así:

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();
}

El almacenamiento de la redirección en la sesión tiene la ventaja de persistir incluso si el usuario omitió sus credenciales o no tiene una cuenta y tiene que registrarse.

Esto también permite que cualquier otra cosa además de Auth establezca una redirección en la sesión y funcionará mágicamente.

vFragosop
fuente
¿No tendría más sentido pasar a la sesión en lugar de poner y olvidar? Su acción de inicio de sesión solo devolvería una redirección al valor en la sesión si existe o la página predeterminada de lo contrario.
bilalq
2
He editado la respuesta para explicar por qué esto es mejor que flash.
vFragosop
Eso tiene sentido. Mejor que volver a parpadear cada vez.
bilalq
1
Cuando se aprueba Auth :: intent (), simplemente puede redirigir al usuario a la página predeterminada (generalmente su página de inicio). Esa redirección pasará por ese filtro nuevamente y lo redirigirá a la URL original solicitada si hay una. De lo contrario, simplemente continuará renderizando su hogar. Pondré un ejemplo de acción de inicio de sesión.
vFragosop
1
en 5.1 está en el middleware RedirectIfAuthenticated.php: if ($ this-> auth-> check ()) {return redirect ('/ privatepage'); }
Dave Driesmans
73

Laravel> = 5.3

Los cambios de Auth en 5.3 hacen que la implementación de esto sea un poco más fácil y ligeramente diferente de 5.2 ya que Auth Middleware se ha movido al contenedor de servicios.

Modifique el nuevo redirector de autenticación de middleware

/app/Http/Middleware/RedirectIfAuthenticated.php

Cambie la función del controlador ligeramente, de modo que se vea así:

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

    return $next($request);
}

TL; explicación DR

La única diferencia está en la 4ta línea; por defecto se ve así:

return redirect("/home");

Dado que Laravel> = 5.3 guarda automáticamente la última ruta "prevista" al verificar Auth Guard, cambia a:

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

Eso le dice a Laravel que redirija a la última página deseada antes de iniciar sesión, de lo contrario vaya a "/ home" o donde desee enviarlos de forma predeterminada.

Espero que esto ayude a alguien más: no hay mucho sobre las diferencias entre 5.2 y 5.3, y en esta área en particular hay bastantes.

Scott Byers
fuente
2
para Laravel 6.4 esto ya no funciona ... alguna idea por favor?
alex toader
Solía return redirect()->intended(RouteServiceProvider::HOME);mantener tu camino a casa en un solo lugar.
Mateusz
26

Encontré esos dos excelentes métodos que pueden ser extremadamente útiles para usted.

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

Puede aplicar este filtro a las rutas que necesitan autenticación.

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

Lo que básicamente hace este método es almacenar la página que intentaba visitar y lo redirige a la página de inicio de sesión .

Cuando el usuario se autentica, puede llamar

return Redirect::intended();

y te redirige a la página que estabas intentando alcanzar al principio.

Es una excelente manera de hacerlo, aunque generalmente uso el siguiente método.

Redirect::back()

Puedes consultar este increíble blog.

giannis christofakis
fuente
Esto es mucho mejor que las soluciones anteriores. Las soluciones anteriores requieren poder pasar un cierre a la función de inicio de sesión que no pude hacer con 4.1. Pero esto fue mucho más simple y funcionó como es.
user2662680
20

Puede usar Redirect :: función prevista . Redirigirá al usuario a la URL a la que intentaba acceder antes de ser detectado por el filtro de autenticación. Se puede dar un URI alternativo a este método en caso de que el destino previsto no esté disponible.

En post iniciar sesión / registrarse:

return Redirect::intended('defaultpageafterlogin');
dabuno
fuente
11

He estado usando esto por un tiempo en mi código de selector de idioma. Siempre que solo necesite retroceder solo 1 página, funciona bien:

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

No es la solución más poderosa que existe, pero es súper fácil y puede ayudar a resolver algunos acertijos. :)

Federico Stango
fuente
55
Sí anterior () funciona bien. Pero si su primer esfuerzo de inicio de sesión falla (por lo que la página 'inicio de sesión fallido' se convierte en su página anterior) y el segundo esfuerzo de inicio de sesión tiene éxito, se lo redirige a la página de inicio de sesión nuevamente (lo que puede redirigirlo a la página de inicio).
Shriganesh Shintre
11

Cambie su constructor LoginControllers a:

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

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

Le redirigirá a la página ANTES de la página de inicio de sesión (2 páginas atrás).

MevlütÖzdemir
fuente
El único que funciona para mí. Debe significar que tengo otra redirección sucediendo en algún lugar pero quién sabe dónde.
Arthur Tarasov
8
return Redirect::intended('/');

esto lo redirigirá a la página predeterminada de su proyecto, es decir, la página de inicio.

Parag Bhingre
fuente
6

Para laravel 5. * prueba estos.

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

o

return Redirect::intended('/');
Nuruzzaman Milon
fuente
5

Laravel 3

Modifiqué un poco su código (Vinícius Fragoso Pinheiro) y coloqué lo siguiente en filtros.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');
    }
});

Y luego dentro de mi 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'));
}

Tenga en cuenta que el 'redirect' datos de sesión se actualizan si hay un problema de autenticación. Esto mantiene la redirección intacta durante cualquier contratiempo de inicio de sesión, pero si el usuario hace clic en cualquier punto, el siguiente proceso de inicio de sesión no se ve interrumpido por los datos de la sesión.

También debe actualizar los datos en el punto de mostrar el formulario de inicio de sesión en su AuthController, de lo contrario, la cadena se rompe:

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');
}
Joe Richards
fuente
3

Utilizar Redirect;

Entonces usa esto:

return Redirect::back();
ujwal dhakal
fuente
0

Larvel 5.3 esto realmente funcionó para mí simplemente actualizando 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;
}

ref: https://laracasts.com/discuss/channels/laravel/redirect-to-previous-page-after-login

Nomi
fuente
0

Para Laravel 5.5 y probablemente 5.4

En App \ Http \ Middleware \ RedirectIfAuthenticated change redirect('/home')to redirect()->intended('/home')en la función de manejo:

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

    return $next($request);
}

en App \ Http \ Controllers \ Auth \ LoginController, cree la showLoginForm()función de la siguiente manera:

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

De esta manera, si hubo una intención para otra página, se redirigirá allí; de lo contrario, se redirigirá a casa.

DerDare
fuente
0

Estoy usando el siguiente enfoque con un controlador de inicio de sesión personalizado y middleware para Laravel 5.7, pero espero que funcione en cualquiera de las versiones de laravel 5

  • middleware interior

    if (Auth::check()){
        return $next($request);
    }
    else{
      return redirect()->guest(route('login'));
    }
  • método de inicio de sesión del controlador interno

    if (Auth::attempt(['email' => $email, 'password' => $password])) {
    return redirect()->intended('/default');
    }
  • Si necesita pasar la URL deseada al lado del cliente , puede intentar lo siguiente

       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);
        }
Nayeem Azad
fuente
0

Primero, debe saber cómo redirige al usuario a la ruta de 'inicio de sesión':

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

Así no:

return redirect()->intended('/signin');
Odilov Oybek
fuente
0

¡Laravel ahora es compatible con esta función lista para usar! (Creo que desde 5.5 o anterior).

Agregue un __construct()método a su Controllercomo se muestra a continuación:

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

Después de iniciar sesión, sus usuarios serán redirigidos a la página que pretendían visitar inicialmente.

También puede agregar la función de verificación de correo electrónico de Laravel según lo requiera la lógica de su aplicación:

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

La documentación contiene un ejemplo muy breve:

También es posible elegir a qué métodos de controlador se aplica el middleware usando except u onlyopciones.

Ejemplo con except:

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

Ejemplo con only:

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

Más información sobre excepty onlyopciones de middleware:

LangostaBaz
fuente
0

si está utilizando axios u otra biblioteca AJAX javascript, puede que desee recuperar la url y pasar al front end

puedes hacerlo con el siguiente código

   $default = '/';

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

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

Esto devolverá una cadena con formato json

Emmanuel David
fuente
0

En Laravel 5.8

en App \ Http \ Controllers \ Auth \ LoginController agregue el siguiente método

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

en App \ Http \ Middleware \ RedirectIfAuthenticated reemplace "return redirect ('/ home');" con lo siguiente

 if (Auth::guard($guard)->check()) 
    {
        return redirect()->intended();
    }
Yann Boyongo
fuente
-1

¿Intentaste esto en tu route.php?

Route::group(['middleware' => ['web']], function () {
    //
    Route::get('/','HomeController@index');
});
Arios
fuente
-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');
}
programador genial
fuente
2
Proporcione algunos comentarios que acompañen a su código para proporcionar algún contexto. Gracias
Suever
-1

Aquí está mi solución para 5.1. Necesitaba que alguien haga clic en el botón "Me gusta" en una publicación, sea redirigido para iniciar sesión y luego regrese a la página original. Si ya habían iniciado sesión, elhref botón "Me gusta" se interceptó con JavaScript y se convirtió en una solicitud AJAX.

El botón es algo así <a href="https://stackoverflow.com/like/931">Like This Post!</a>. /like/931es manejado por un LikeController que requiereauth middleware.

En Authenticate middleware (la handle()función), agregue algo como esto al principio:

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

Cambie /auth/logina la URL que sea para iniciar sesión. Este código guarda la URL de la página original en la sesión a menos que la URL sea la URL de inicio de sesión. Esto es obligatorio porque parece que este middleware se llama dos veces. No estoy seguro de por qué o si eso es cierto. Pero si no verifica ese condicional, será igual a la página original correcta y, de alguna manera, tendrá la oportunidad de/auth/login . Probablemente haya una forma más elegante de hacer esto.

Luego, en LikeControllero en el controlador que tenga que maneje la URL del botón presionado en la página original:

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

Este método es súper simple, no requiere anular ninguna función existente y funciona muy bien. Es posible que Laravel pueda hacer esto de una manera más fácil, pero no estoy seguro de qué es. Usar la intended()función no funciona en mi caso porque LikeController también necesitaba saber cuál era la URL anterior para redirigirla de nuevo. Esencialmente dos niveles de redireccionamiento hacia atrás.

Brynn Bateman
fuente
-1

Para Laravel 5.2 (versiones anteriores que no usé)

Pegue el código en la aplicación de archivo \ 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*/
}

E importar el espacio de nombres: use Session;

Si no ha realizado ningún cambio en la aplicación de archivo \ Http \ Controllers \ Auth \ AurhController.php, puede reemplazarlo con el archivo de GitHub

zdorovo
fuente
-1

Laravel 5.2

Si está utilizando otro Middleware como el middleware de Admin , puede configurar una sesión para url.intended usando lo siguiente:

Básicamente, necesitamos configurarlo manualmente \Session::put('url.intended', \URL::full());para la redirección.

Ejemplo

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

En el intento de inicio de sesión

Asegúrese de utilizar el intento de inicio de sesión return \Redirect::intended('default_path');

Rashedul Islam Sagor
fuente
Para eso redirect()->guest('login')es eso .
Emile Bergeron
-1

Para Laravle 5.7, debe realizar el cambio en:

Middleware> RedirectIfAuthenticated.php

Cambia esto:

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

        return $next($request);
    }

A esto:

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

        return $next($request);
    }

volver a redireccionar ('/ yourpath');

El príncipe Ahmed
fuente
¿Qué es mypath? (pase de usuario para volver a esto)
Mostafa Norzade