Laravel登录后重定向回原始目的地


189

这似乎是一个非常基本的流程,并且Laravel对基本事物有很多不错的解决方案,我觉得我缺少一些东西。

用户单击需要身份验证的链接。Laravel的身份验证过滤器启动,并将其路由到登录页面。用户登录,然后转到他们尝试访问的原始页面,然后再启动“身份验证”过滤器。

是否有一种很好的方法来知道他们最初尝试访问的页面?由于Laravel是拦截请求的人,因此我不知道用户登录后它是否在某个地方保持跟踪以便轻松路由。

如果没有,我很想知道你们中的一些人是如何手动实现的。

Answers:


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

将重定向存储在Session上的好处是可以持久保存该重定向,即使用户错过键入凭据或他没有帐户且必须注册也是如此。

除了Auth以外,这还允许在会话上设置重定向的其他方法,它将神奇地起作用。


闪动到会话而不是放后忘记会更有意义吗?您的登录操作只会将重定向返回到会话中的值(如果存在),否则将返回默认页面。
bilalq

2
我已经编辑了答案,以解释为什么它比Flash更好。
vFragosop 2013年

这就说得通了。比每次刷新都要好。
bilalq

1
当Auth :: attempt()通过时,您可以简单地将用户重定向到默认页面(通常是他的主页)。重定向将再次通过该过滤器,如果存在,它将重定向到原始请求的URL。否则,它将继续继续渲染他的房屋。我将以登录操作为例。
vFragosop 2013年

1
在5.1中,它位于中间件RedirectIfAuthenticated.php中:if($ this-> auth-> check()){return redirect('/ privatepage'); }
Dave Driesmans

72

Laravel> = 5.3

由于Auth中间件已移至服务容器,因此5.3中的Auth更改使此实现更容易一些,并且与5.2略有不同。

修改新的中间件身份验证重定向器

/app/Http/Middleware/RedirectIfAuthenticated.php

稍微更改handle函数,如下所示:

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

    return $next($request);
}

TL; DR说明

唯一的不同是在第四行。默认情况下,它看起来像这样:

return redirect("/home");

由于Laravel> = 5.3在检查Auth Guard时自动保存了最后一个“预定”路由,因此更改为:

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

这告诉Laravel在登录之前重定向到最后一个预期的页面,否则转到“ / home”或默认情况下您希望将其发送到的任何地方。

希望这对其他人有帮助-5.2和5.3之间的区别不多,尤其是在这一方面。


2
对于Laravel 6.4,这将不再起作用...有任何想法吗?
亚历克斯·蟾蜍

我会习惯于return redirect()->intended(RouteServiceProvider::HOME);将您的家庭路径放在一个地方。
Mateusz

26

我发现这两种很棒的方法可能对您非常有帮助。

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

您可以将此过滤器应用于需要身份验证的路由。

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

此方法的基本作用是存储您尝试访问的页面,并将您重定向到登录页面。

用户通过身份验证后,您可以致电

return Redirect::intended();

它将您重定向到您最初尝试访问的页面。

尽管我通常使用以下方法,但这是一种很好的方法。

Redirect::back()

您可以查看这个很棒的博客。


这比上面的解决方案好得多。上面的解决方案要求能够将闭包传递给登录功能,而4.1是我无法做到的。但这要简单得多,并且照原样工作。
user2662680 '18

20

您可以使用Redirect :: intended函数。它将用户重定向到他们尝试访问的URL,然后再被Authenticaton过滤器捕获。如果预期的目标位置不可用,则可以为此方法提供后备URI。

在登录/注册后:

return Redirect::intended('defaultpageafterlogin');

11

我在语言选择器代码上使用了一段时间。只要您只需要返回上一页,它就可以正常工作:

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

它不是那里最强大的解决方案,但它非常简单,可以帮助解决一些难题。:)


5
是的,previous()可以正常工作。但是,如果您的第一次登录失败(因此“登录失败”页面将成为您的上一页),而第二次登录成功,则您将再次重定向到登录页面(这可能会将您重定向到主页)。
Shriganesh Shintre

11

将您的LoginControllers构造函数更改为:

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

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

它会将您重定向到登录页面之前的页面(后退2页)。


唯一对我有用的。这必须表示我在某处发生了另一个重定向,但是谁知道在哪里。
亚瑟·塔拉索夫

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

这会将您重定向到项目的默认页面,即开始页面。



5

Laravel 3

我略微调整了您的(ViníciusFragoso 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');
}


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

这样,如果有另一个页面的意图,它将重定向到该页面,否则它将重定向到主页。


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');
    }
  • 如果您需要将目标网址传递给客户端,则可以尝试以下操作

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

有关exceptonly中间件选项的更多信息:


0

如果您使用的是axios或其他AJAX javascript库,则可能要获取该URL并传递给前端

你可以用下面的代码做到这一点

   $default = '/';

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

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

这将返回一个json格式的字符串


0

在Laravel 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中,将“ return redirect('/ home');”替换为以下内容

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

-1

您是否在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
请提供一些注释以及代码,以提供一些上下文。谢谢
Suever 2016年

-1

这是我的5.1解决方案。我需要有人单击帖子上的“赞”按钮,重定向到登录名,然后返回到原始页面。如果他们已经登录,则href“ Like”按钮的会被JavaScript拦截,并转换为AJAX请求。

该按钮类似于<a href="https://stackoverflow.com/like/931">Like This Post!</a>/like/931由需要auth中间件的LikeController处理。

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

该方法非常简单,不需要覆盖任何现有功能,效果很好。Laravel可能有一些更简单的方法来执行此操作,但是我不确定它是什么。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

如果您正在使用其他中间件(例如Admin中间件),则可以使用以下命令为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')是为了什么
Emile Bergeron

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

返回redirect('/ yourpath');


什么mypath啊 (用户请返回
此处
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.