O Laravel redireciona de volta ao destino original após o login


188

Parece um fluxo bastante básico e Laraveltem tantas soluções legais para coisas básicas que sinto que estou perdendo alguma coisa.

Um usuário clica em um link que requer autenticação. O filtro de autenticação do Laravel entra em ação e os direciona para uma página de login. O usuário efetua login e depois acessa a página original que estava tentando acessar antes do filtro 'auth' aparecer.

Existe uma boa maneira de saber a que página eles estavam tentando acessar originalmente? Como o Laravel é quem intercepta a solicitação, eu não sabia se ele acompanha algum lugar para facilitar o roteamento após o usuário fazer login.

Caso contrário, ficaria curioso para saber como alguns de vocês implementaram isso manualmente.

Respostas:


234

Para o Laravel 5.3 e superior

Verifique a resposta de Scott abaixo.

Para o Laravel 5 até 5.2

Simplificando,

No middleware de autenticação:

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

Na ação de 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');
}

Para o Laravel 4 (resposta antiga)

No momento desta resposta, não havia suporte oficial da própria estrutura. Hoje em dia você pode usaro método indicado por bgdrl abaixoeste método: (tentei atualizar sua resposta, mas parece que ele não aceitará)

No filtro de autenticação:

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

Na ação de 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');
}

Para o Laravel 3 (resposta ainda mais antiga)

Você poderia implementá-lo assim:

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

Armazenar o redirecionamento na Sessão tem o benefício de persistir, mesmo que o usuário tenha digitado suas credenciais ou ele não tenha uma conta e precise se inscrever.

Isso também permite que qualquer outra coisa além de Auth defina um redirecionamento na sessão e funcionará magicamente.


Não faria mais sentido passar para a sessão em vez de colocar e esquecer? Sua ação de login retornaria um redirecionamento para o valor na sessão, se existir, ou a página padrão, caso contrário.
bilalq

2
Editei a resposta para explicar por que isso é melhor que o flash.
vFragosop

Isso faz sentido. Melhor do que refletir cada vez.
bilalq

1
Quando Auth :: try () passa, você pode simplesmente redirecionar o usuário para a página padrão (geralmente a casa dele). Esse redirecionamento passará por esse filtro novamente e o redirecionará para o URL solicitado original, se houver um. Caso contrário, ele simplesmente continuará renderizando sua casa. Vou colocar um exemplo de ação de login.
vFragosop

1
no 5.1 está no middleware RedirectIfAuthenticated.php: if ($ this-> auth-> check ()) {return redirect ('/ privatepage'); }
Dave Driesmans 15/06/2015

72

Laravel> = 5.3

As alterações de autenticação na versão 5.3 tornam a implementação um pouco mais fácil e um pouco diferente da 5.2, desde que o Auth Middleware foi movido para o contêiner de serviço.

Modifique o novo redirecionador de autenticação Middleware

/app/Http/Middleware/RedirectIfAuthenticated.php

Altere a função do identificador levemente, para que fique assim:

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

    return $next($request);
}

Explicação TL; DR

A única diferença está na quarta linha; por padrão, fica assim:

return redirect("/home");

Como o Laravel> = 5.3 salva automaticamente a última rota "pretendida" ao verificar o Auth Guard, ele muda para:

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

Isso diz ao Laravel para redirecionar para a última página pretendida antes do login, caso contrário, vá para "/ home" ou para onde você quiser enviá-los por padrão.

Espero que isso ajude outra pessoa - não há muito por aí sobre as diferenças entre 5.2 e 5.3, e nessa área em particular, existem algumas.


1
para o Laravel 6.4 isso não está mais funcionando ... alguma ideia pls?
Alex Toader

Eu usaria return redirect()->intended(RouteServiceProvider::HOME);para manter o caminho da sua casa em um só lugar.
Mateusz

26

Eu encontrei esses dois ótimos métodos que podem ser extremamente úteis para você.

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

Você pode aplicar esse filtro às rotas que precisam de autenticação.

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

O que esse método basicamente faz é armazenar a página que você estava tentando visitar e redirecioná-lo para a página de login .

Quando o usuário é autenticado, você pode ligar

return Redirect::intended();

e ele o redireciona para a página que você estava tentando acessar primeiro.

É uma ótima maneira de fazer isso, embora eu normalmente use o método abaixo.

Redirect::back()

Você pode conferir este blog incrível.


Isso é muito melhor do que as soluções acima. As soluções acima exigem ser capaz de passar um fechamento para a função de login que eu não poderia fazer com o 4.1. Mas isso foi muito mais simples e funcionou como está.
precisa saber é o seguinte

20

Você pode usar a função Redirect :: intencionada . Ele redirecionará o usuário para o URL que eles estavam tentando acessar antes de serem capturados pelo filtro de autenticação. Um URI de fallback pode ser fornecido para esse método, caso o destino pretendido não esteja disponível.

No pós-login / registro:

return Redirect::intended('defaultpageafterlogin');

11

Eu tenho usado isso por um tempo no meu código seletor de idioma. Contanto que você só precise voltar em apenas 1 página, funciona bem:

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

Não é a solução mais poderosa disponível, mas é super fácil e pode ajudar a resolver alguns quebra-cabeças. :)


5
Sim previous () funciona bem. Mas se o seu primeiro esforço de login falhar (a página 'falha no login' se torna a página anterior) e o segundo esforço for bem-sucedido, você será redirecionado para a página de login novamente (o que poderá redirecioná-lo para a página inicial).
Shriganesh Shintre

11

Altere o construtor LoginControllers para:

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

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

Ele o redirecionará de volta para a página ANTES da página de login (2 páginas atrás).


O único que funciona para mim. Deve significar que tenho outro redirecionamento acontecendo em algum lugar, mas quem sabe onde.
Arthur Tarasov

8
return Redirect::intended('/');

isso o redirecionará para a página padrão do seu projeto, ou seja, a página inicial.


6

Para o laravel 5. * tente estes.

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

ou

return Redirect::intended('/');

5

Laravel 3

Alterei um pouco o seu código (Vinícius Fragoso Pinheiro) e coloquei o seguinte em 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');
    }
});

E então dentro do meu 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'));
}

Observe que os 'redirect'dados da sessão são atualizados novamente se houver um problema de autenticação. Isso mantém o redirecionamento intacto durante qualquer problema no logon, mas se o usuário clicar a qualquer momento, o próximo processo de logon não será interrompido pelos dados da sessão.

Você também precisa atualizar novamente os dados no momento de mostrar o formulário de login no seu AuthController, caso contrário, a cadeia será interrompida:

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


0

Para o Laravel 5.5 e provavelmente 5.4

Em App \ Http \ Middleware \ RedirectIfAuthenticated, altere redirect('/home')para redirect()->intended('/home')na função de identificador:

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

    return $next($request);
}

em App \ Http \ Controllers \ Auth \ LoginController, crie a showLoginForm()função da seguinte maneira:

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

Dessa forma, se houver uma intenção para outra página, ela será redirecionada para lá, caso contrário, será redirecionada para casa.


0

Estou usando a seguinte abordagem com um controlador de login personalizado e middleware para o Laravel 5.7, mas espero que funcione em qualquer uma das versões do laravel 5

  • dentro do middleware

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

    if (Auth::attempt(['email' => $email, 'password' => $password])) {
    return redirect()->intended('/default');
    }
  • Se você precisar passar o URL pretendido para o lado do cliente , tente o seguinte

       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

Primeiro, você deve saber como redirecionar o usuário para a rota de 'login':

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

Assim não:

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

0

O Laravel agora suporta esse recurso pronto para uso! (Acredito desde 5.5 ou anterior).

Adicione um __construct()método ao seu Controllercomo mostrado abaixo:

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

Após o login, seus usuários serão redirecionados para a página que pretendiam visitar inicialmente.

Você também pode adicionar o recurso de verificação de email do Laravel, conforme exigido pela lógica da sua aplicação:

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

A documentação contém um exemplo muito breve:

Também é possível escolher a quais métodos do controlador o middleware se aplica usando except ou onlyoptions.

Exemplo com except:

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

Exemplo com only:

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

Mais informações sobre excepte onlyopções de middleware:


0

se você estiver usando axios ou outra biblioteca javascript AJAX, poderá recuperar o URL e passar para o front end

você pode fazer isso com o código abaixo

   $default = '/';

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

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

Isso retornará uma string formatada em json


0

No Laravel 5.8

em App \ Http \ Controllers \ Auth \ LoginController, adicione o seguinte método

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

em App \ Http \ Middleware \ RedirectIfAuthenticated, substitua "return redirect ('/ home');" pelo seguinte

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

-1

Você tentou isso no seu routes.php?

Route::group(['middleware' => ['web']], function () {
    //
    Route::get('/','HomeController@index');
});

-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
Forneça alguns comentários para acompanhar seu código e fornecer algum contexto. Obrigado
Suever

-1

Aqui está a minha solução para o 5.1. Eu precisava de alguém para clicar no botão "Curtir" em uma postagem, ser redirecionado para o login e retornar à página original. Se eles já estavam logados, o hrefbotão "Curtir" foi interceptado com JavaScript e transformado em uma solicitação AJAX.

O botão é algo parecido <a href="https://stackoverflow.com/like/931">Like This Post!</a>. /like/931é tratado por um LikeController que requer o authmiddleware.

No middleware Authenticate (a handle()função), adicione algo assim no início:

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

Altere /auth/loginpara o URL desejado para fazer login. Esse código salva o URL da página original na sessão, a menos que o URL seja o URL de login. Isso é necessário porque parece que esse middleware foi chamado duas vezes. Não sei por que ou se isso é verdade. Mas se você não verificar essa condicional, ela será igual à página original correta e, de alguma forma, será alterada /auth/login. Provavelmente existe uma maneira mais elegante de fazer isso.

Em seguida, no LikeControllercontrolador ou em qualquer controlador que você lida com o URL do botão pressionado na página original:

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

Este método é super simples, não requer a substituição de nenhuma função existente e funciona muito bem. É possível que haja alguma maneira mais fácil para o Laravel fazer isso, mas não tenho certeza do que seja. Usar a intended()função não funciona no meu caso, porque o LikeController também precisava saber qual era o URL anterior para redirecioná-lo novamente. Essencialmente dois níveis de redirecionamento para trás.


-1

Para o Laravel 5.2 (versões anteriores não usei)

Cole o código no arquivo 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*/
}

E importe o namespace: use Session;

Se você não fez nenhuma alteração no arquivo app \ Http \ Controllers \ Auth \ AurhController.php, basta substituí-lo pelo arquivo do GitHub


-1

Laravel 5.2

Se você estiver usando outro Middleware como o Middleware Admin, poderá definir uma sessão para url.intended usando o seguinte:

Basicamente, precisamos definir manualmente o \Session::put('url.intended', \URL::full());redirecionamento.

Exemplo

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

Na tentativa de login

Certifique-se de que na tentativa de login use return \Redirect::intended('default_path');


Isso é o que redirect()->guest('login')é para.
Emile Bergeron

-1

O Larvel 5.3 realmente funcionou para mim, apenas atualizando o 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


-1

Para o Laravle 5.7, você precisa fazer alterações em:

Middleware> RedirectIfAuthenticated.php

Mude isso:

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

        return $next($request);
    }

Para isso:

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

        return $next($request);
    }

retornar redirecionamento ('/ yourpath');


O que é mypath? (Usuário passar para voltar a esta)
Mostafa Norzade
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.