Redirection Laravel vers la destination d'origine après la connexion

189

Cela semble être un flux assez basique, et Laravela tellement de bonnes solutions pour les choses de base, j'ai l'impression que je manque quelque chose.

Un utilisateur clique sur un lien qui nécessite une authentification. Le filtre d' authentification de Laravel entre en action et les dirige vers une page de connexion. L'utilisateur se connecte, puis accède à la page d'origine à laquelle il essayait d'accéder avant que le filtre «auth» ne soit activé.

Existe-t-il un bon moyen de savoir à quelle page ils essayaient d'accéder à l'origine? Étant donné que Laravel est celui qui intercepte la demande, je ne savais pas s'il gardait une trace quelque part pour un routage facile après la connexion de l'utilisateur.

Sinon, je serais curieux de savoir comment certains d'entre vous l'ont implémenté manuellement.

JOV
la source

Réponses:

234

Pour Laravel 5.3 et supérieur

Vérifiez la réponse de Scott ci-dessous.

Pour Laravel 5 jusqu'à 5,2

Tout simplement,

Sur le middleware d'authentification:

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

Lors de l'action de connexion:

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

Pour Laravel 4 (ancienne réponse)

Au moment de cette réponse, il n'y avait aucun soutien officiel du cadre lui-même. De nos jours, vous pouvez utiliserla méthode indiquée par bgdrl ci-dessouscette méthode: (j'ai essayé de mettre à jour sa réponse, mais il semble qu'il n'acceptera pas)

Sur le filtre d'authentification:

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

Lors de l'action de connexion:

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

Pour Laravel 3 (réponse encore plus ancienne)

Vous pouvez l'implémenter comme ceci:

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

Le stockage de la redirection sur Session a l'avantage de la conserver même si l'utilisateur n'a pas tapé ses informations d'identification ou s'il n'a pas de compte et doit s'inscrire.

Cela permet également à tout autre chose que Auth de définir une redirection en session et cela fonctionnera comme par magie.

vFragosop
la source
Ne serait-il pas plus logique de flasher sur la session plutôt que de mettre et d'oublier? Votre action de connexion renverrait simplement une redirection vers la valeur de la session si elle existe ou la page par défaut sinon.
bilalq
2
J'ai modifié la réponse pour expliquer pourquoi c'est mieux que le flash.
vFragosop
Ça a du sens. Mieux que reflasher à chaque fois.
bilalq
1
Lorsque Auth :: try () réussit, vous pouvez simplement rediriger l'utilisateur vers la page par défaut (généralement son domicile). Cette redirection passera à nouveau par ce filtre et le redirigera vers l'URL demandée d'origine s'il y en a une. Sinon, il continuera simplement à rendre sa maison. Je vais mettre un exemple d'action de connexion.
vFragosop
1
en 5.1, c'est dans le middleware RedirectIfAuthenticated.php: if ($ this-> auth-> check ()) {return redirect ('/ privatepage'); }
Dave Driesmans
73

Laravel> = 5,3

Les modifications d'Auth dans 5.3 rendent l'implémentation de ceci un peu plus facile, et légèrement différente de 5.2 puisque le middleware d'Auth a été déplacé vers le conteneur de service.

Modifier le nouveau redirecteur d'authentification Middleware

/app/Http/Middleware/RedirectIfAuthenticated.php

Modifiez légèrement la fonction de la poignée pour qu'elle ressemble à:

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

    return $next($request);
}

TL; DR explication

La seule différence est dans la 4ème ligne; par défaut, cela ressemble à ceci:

return redirect("/home");

Puisque Laravel> = 5.3 enregistre automatiquement la dernière route "prévue" lors de la vérification de l'Auth Guard, il se transforme en:

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

Cela indique à Laravel de rediriger vers la dernière page prévue avant la connexion, sinon allez dans "/ home" ou à l'endroit où vous souhaitez les envoyer par défaut.

J'espère que cela aide quelqu'un d'autre - il n'y a pas grand-chose sur les différences entre 5.2 et 5.3, et dans ce domaine en particulier, il y en a pas mal.

Scott Byers
la source
2
pour Laravel 6.4 cela ne fonctionne plus ... aucune idée pls?
alex toader du
J'utiliserais return redirect()->intended(RouteServiceProvider::HOME);pour garder votre chemin d'accès à la maison au même endroit.
Mateusz le
26

J'ai trouvé ces deux excellentes méthodes qui pourraient vous être extrêmement utiles.

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

Vous pouvez appliquer ce filtre aux routes qui nécessitent une authentification.

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

Cette méthode sert essentiellement à stocker la page que vous tentiez de visiter et elle vous redirige vers la page de connexion .

Lorsque l'utilisateur est authentifié, vous pouvez appeler

return Redirect::intended();

et il vous redirige vers la page que vous tentiez d'accéder au début.

C'est un excellent moyen de le faire bien que j'utilise généralement la méthode ci-dessous.

Redirect::back()

Vous pouvez consulter ce blog génial.

giannis christofakis
la source
C'est bien mieux que les solutions ci-dessus. Les solutions ci-dessus nécessitent de pouvoir passer une fermeture à la fonction de connexion, ce que je ne pouvais pas faire avec 4.1. Mais c'était beaucoup plus simple et fonctionnait tel quel.
user2662680
20

Vous pouvez utiliser la fonction Redirect :: prévue . Il redirigera l'utilisateur vers l'URL auquel il essayait d'accéder avant d'être intercepté par le filtre d'authentification. Un URI de secours peut être donné à cette méthode au cas où la destination prévue n'est pas disponible.

En post connexion / inscription:

return Redirect::intended('defaultpageafterlogin');
Dabuno
la source
11

J'utilise ceci depuis un moment sur mon code de sélection de langue. Tant que vous n'avez besoin de revenir en arrière que d'une page, cela fonctionne bien:

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

Ce n'est pas la solution la plus puissante du marché, mais elle est très simple et peut aider à résoudre quelques énigmes. :)

Federico Stango
la source
5
Oui, previous () fonctionne bien. Mais si votre premier effort de connexion échoue (ainsi la page `` échec de la connexion '' devient votre page précédente) et que le deuxième effort de connexion réussit, vous êtes redirigé vers la page de connexion (ce qui peut vous rediriger vers la page d'accueil).
Shriganesh Shintre
11

Modifiez votre constructeur LoginControllers en:

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

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

Il vous redirigera vers la page AVANT la page de connexion (2 pages en arrière).

MevlütÖzdemir
la source
Le seul qui fonctionne pour moi. Cela doit signifier que j'ai une autre redirection qui se passe quelque part mais qui sait où.
Arthur Tarasov
8
return Redirect::intended('/');

cela vous redirigera vers la page par défaut de votre projet, c'est-à-dire la page de démarrage.

Parag Bhingre
la source
6

Pour laravel 5. * essayez-les.

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

ou

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

Laravel 3

J'ai légèrement modifié votre code (Vinícius Fragoso Pinheiro) et placé ce qui suit dans 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');
    }
});

Et puis dans le my 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'));
}

Notez que les 'redirect'données de session sont reflétées s'il y a un problème d'authentification. Cela permet de garder la redirection intacte pendant tout incident de connexion, mais si l'utilisateur clique à tout moment, le processus de connexion suivant n'est pas perturbé par les données de session.

Vous devez également reflasher les données au moment d'afficher le formulaire de connexion dans votre AuthController, sinon la chaîne est rompue:

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
la source
3

Utilisation Redirect;

Ensuite, utilisez ceci:

return Redirect::back();
ujwal dhakal
la source
0

Larvel 5.3 cela a fonctionné pour moi en mettant simplement à jour 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;
}

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

Nomi
la source
0

Pour Laravel 5.5 et probablement 5.4

Dans App \ Http \ Middleware \ RedirectIfAuthenticated changement redirect('/home')à redirect()->intended('/home')la fonction de poignée:

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

    return $next($request);
}

dans App \ Http \ Controllers \ Auth \ LoginController, créez la showLoginForm()fonction comme suit:

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

De cette façon, s'il y avait une intention pour une autre page, elle s'y redirigera sinon elle redirigera vers la maison.

DerDare
la source
0

J'utilise l'approche suivante avec un contrôleur de connexion personnalisé et un middleware pour Laravel 5.7, mais j'espère que cela fonctionne dans l'une des versions de laravel 5

  • à l'intérieur du middleware

    if (Auth::check()){
        return $next($request);
    }
    else{
      return redirect()->guest(route('login'));
    }
  • à l'intérieur de la méthode de connexion du contrôleur

    if (Auth::attempt(['email' => $email, 'password' => $password])) {
    return redirect()->intended('/default');
    }
  • Si vous devez transmettre l'URL intentionnelle côté client , vous pouvez essayer ce qui suit

       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
la source
0

Tout d'abord, vous devez savoir comment vous redirigez l'utilisateur vers la route de `` connexion '':

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

Pas comme ça:

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

Laravel prend désormais en charge cette fonctionnalité prête à l'emploi! (Je crois depuis 5.5 ou plus tôt).

Ajoutez une __construct()méthode à votre Controllercomme indiqué ci-dessous:

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

Après la connexion, vos utilisateurs seront alors redirigés vers la page qu'ils avaient l'intention de visiter initialement.

Vous pouvez également ajouter la fonction de vérification des e-mails de Laravel selon les besoins de votre logique d'application:

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

La documentation contient un très bref exemple:

Il est également possible de choisir les méthodes de contrôleur auxquelles le middleware s'applique en utilisant les options except ou only.

Exemple avec except:

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

Exemple avec only:

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

Plus d'informations sur exceptet onlyles options middleware:

HomardBaz
la source
0

si vous utilisez axios ou une autre bibliothèque javascript AJAX, vous souhaiterez peut-être récupérer l'url et la transmettre au frontal

vous pouvez le faire avec le code ci-dessous

   $default = '/';

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

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

Cela renverra une chaîne au format json

Emmanuel David
la source
0

Dans Laravel 5.8

dans App \ Http \ Controllers \ Auth \ LoginController, ajoutez la méthode suivante

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

dans App \ Http \ Middleware \ RedirectIfAuthenticated, remplacez "return redirect ('/ home');" par ce qui suit

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

Avez-vous essayé cela dans votre routes.php?

Route::group(['middleware' => ['web']], function () {
    //
    Route::get('/','HomeController@index');
});
Arios
la source
-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');
}
programmeur cool
la source
2
Veuillez fournir quelques commentaires accompagnant votre code pour fournir un contexte. Merci
Suever
-1

Voici ma solution pour 5.1. J'avais besoin que quelqu'un clique sur un bouton «J'aime» sur un message, soit redirigé vers la connexion, puis revienne à la page d'origine. S'ils étaient déjà connectés, le hrefbouton "J'aime" a été intercepté avec JavaScript et transformé en requête AJAX.

Le bouton est quelque chose comme <a href="https://stackoverflow.com/like/931">Like This Post!</a>. /like/931est géré par un LikeController qui nécessite le authmiddleware.

Dans le middleware Authenticate (la handle()fonction), ajoutez quelque chose comme ceci au début:

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

Modifiez /auth/loginvotre URL pour vous connecter. Ce code enregistre l'URL de la page d'origine dans la session, sauf si l'URL est l'URL de connexion. Ceci est nécessaire car il semble que ce middleware soit appelé deux fois. Je ne sais pas pourquoi ni si c'est vrai. Mais si vous ne vérifiez pas ce conditionnel, il sera égal à la page d'origine correcte, puis sera changé d'une manière ou d'une autre /auth/login. Il existe probablement une manière plus élégante de le faire.

Ensuite, dans le LikeControllercontrôleur ou tout autre contrôleur que vous avez qui gère l'URL du bouton enfoncé sur la page d'origine:

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

Cette méthode est super simple, ne nécessite pas de remplacer les fonctions existantes et fonctionne très bien. Il est possible qu'il existe un moyen plus simple pour Laravel de le faire, mais je ne suis pas sûr de ce que c'est. L'utilisation de la intended()fonction ne fonctionne pas dans mon cas car le LikeController devait également savoir quelle était l'URL précédente pour y rediriger. Essentiellement deux niveaux de redirection vers l'arrière.

Brynn Bateman
la source
-1

Pour Laravel 5.2 (versions précédentes que je n'ai pas utilisées)

Collez le code dans le fichier 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*/
}

Et importez l'espace de noms: use Session;

Si vous n'avez apporté aucune modification au fichier app \ Http \ Controllers \ Auth \ AurhController.php, vous pouvez simplement le remplacer par le fichier du GitHub

zdorovo
la source
-1

Laravel 5.2

Si vous utilisez un autre middleware tel que le middleware Admin, vous pouvez définir une session pour url.intended en utilisant ce qui suit:

Fondamentalement, nous devons définir manuellement \Session::put('url.intended', \URL::full()); redirection.

Exemple

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

Lors de la tentative de connexion

Assurez-vous que lors de la tentative de connexion, utilisez return \Redirect::intended('default_path');

Rashedul Islam Sagor
la source
C'est à ça que ça redirect()->guest('login')sert.
Emile Bergeron
-1

Pour Laravle 5.7, vous devez modifier:

Intergiciel> RedirectIfAuthenticated.php

Change ça:

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

        return $next($request);
    }

Pour ça:

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

        return $next($request);
    }

return redirect ('/ yourpath');

Prince Ahmed
la source
Qu'est-ce que c'est mypath? (pass utilisateur pour revenir à cela)
Mostafa Norzade