Laravel chuyển hướng trở lại đích ban đầu sau khi đăng nhập


188

Đây có vẻ là một luồng khá cơ bản và Laravelcó rất nhiều giải pháp tốt cho những điều cơ bản, tôi cảm thấy như mình đang thiếu thứ gì đó.

Một người dùng nhấp vào một liên kết yêu cầu xác thực. Bộ lọc xác thực của Laravel khởi động và định tuyến chúng đến trang đăng nhập. Người dùng đăng nhập, sau đó truy cập trang gốc mà họ đang cố truy cập trước khi bộ lọc 'auth' khởi động.

Có cách nào tốt để biết trang nào họ đang cố gắng truy cập ban đầu không? Vì Laravel là người chặn yêu cầu, tôi không biết liệu nó có theo dõi ở đâu đó để dễ dàng định tuyến sau khi người dùng đăng nhập không.

Nếu không, tôi tò mò muốn biết làm thế nào một số bạn đã thực hiện điều này bằng tay.

Câu trả lời:


234

Dành cho Laravel 5.3 trở lên

Kiểm tra câu trả lời của Scott dưới đây.

Đối với Laravel 5 lên tới 5,2

Chỉ cần đặt,

Trên phần mềm trung gian auth:

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

Về hành động đăng nhập:

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

Dành cho Laravel 4 (câu trả lời cũ)

Tại thời điểm trả lời này, không có hỗ trợ chính thức từ chính khuôn khổ. Ngày nay bạn có thể sử dụngphương pháp được chỉ ra bởi bgdrl bên dướiphương pháp này: (Tôi đã thử cập nhật câu trả lời của anh ấy, nhưng có vẻ như anh ấy sẽ không chấp nhận)

Trên bộ lọc xác thực:

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

Về hành động đăng nhập:

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

Dành cho Laravel 3 (câu trả lời thậm chí cũ hơn)

Bạn có thể thực hiện nó như thế này:

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

Lưu trữ chuyển hướng trên Phiên có lợi ích duy trì nó ngay cả khi người dùng bỏ lỡ nhập thông tin đăng nhập của mình hoặc anh ta không có tài khoản và phải đăng ký.

Điều này cũng cho phép mọi thứ khác ngoài Auth đặt chuyển hướng trên phiên và nó sẽ hoạt động một cách kỳ diệu.


Nó sẽ không có ý nghĩa hơn để flash vào phiên hơn là đặt và quên? Hành động đăng nhập của bạn sẽ chỉ trả lại một chuyển hướng đến giá trị trong phiên nếu nó tồn tại hoặc trang mặc định khác.
bilalq

2
Tôi đã chỉnh sửa câu trả lời để giải thích tại sao điều này tốt hơn flash.
vFragosop

Điều đó có ý nghĩa. Tốt hơn là phản xạ mỗi lần.
bilalq

1
Khi Auth :: vor () vượt qua, bạn chỉ cần chuyển hướng người dùng đến trang mặc định (thường là nhà của anh ta). Chuyển hướng đó sẽ đi qua bộ lọc đó một lần nữa và nó sẽ chuyển hướng anh ta đến URL được yêu cầu ban đầu nếu có. Nếu không, nó sẽ chỉ tiếp tục kết xuất nhà của mình. Tôi sẽ đưa ra một ví dụ về hành động đăng nhập.
vFragosop

1
trong 5.1 nó có trong phần mềm trung gian Redirect IfAuthenticated.php: if ($ this-> auth-> check ()) {return redirect ('/ privatepage'); }
Dave Driesmans

72

Ấu trùng> = 5,3

Các thay đổi Auth trong 5.3 giúp việc thực hiện việc này dễ dàng hơn một chút và khác một chút so với 5.2 do Auth Middleware đã được chuyển sang vùng chứa dịch vụ.

Sửa đổi trình chuyển hướng auth Middleware mới

/app/Http/Middleware/RedirectIfAuthenticated.php

Thay đổi chức năng xử lý một chút, vì vậy nó trông giống như:

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

    return $next($request);
}

TL; DR giải thích

Sự khác biệt duy nhất là trong dòng thứ 4; theo mặc định nó trông như thế này:

return redirect("/home");

Vì Laravel> = 5.3 tự động lưu tuyến đường "dự định" cuối cùng khi kiểm tra Auth Guard, nên nó thay đổi thành:

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

Điều đó nói với Laravel chuyển hướng đến trang dự định cuối cùng trước khi đăng nhập, nếu không, hãy truy cập "/ home" hoặc bất cứ nơi nào bạn muốn gửi chúng theo mặc định.

Hy vọng điều này sẽ giúp được người khác - không có nhiều khác biệt về sự khác biệt giữa 5.2 và 5.3, và trong lĩnh vực này nói riêng có khá nhiều.


1
Đối với Laravel 6.4, điều này không còn hoạt động nữa ... có ý kiến ​​gì không?
alex toader

Tôi sẽ sử dụng return redirect()->intended(RouteServiceProvider::HOME);để giữ đường dẫn nhà của bạn ở một nơi.
Mateusz

26

Tôi thấy hai phương pháp tuyệt vời đó có thể cực kỳ hữu ích cho bạn.

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

Bạn có thể áp dụng bộ lọc này cho các tuyến cần xác thực.

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

Phương pháp này về cơ bản là gì để lưu trữ trang bạn đang cố truy cập và nó chuyển hướng bạn đến trang đăng nhập .

Khi người dùng được xác thực, bạn có thể gọi

return Redirect::intended();

và nó chuyển hướng bạn đến trang bạn đang cố truy cập lúc đầu.

Đó là một cách tuyệt vời để làm điều đó mặc dù tôi thường sử dụng phương pháp dưới đây.

Redirect::back()

Bạn có thể kiểm tra blog tuyệt vời này .


Điều này tốt hơn nhiều so với các giải pháp trên. Các giải pháp trên yêu cầu có thể vượt qua việc đóng cửa với chức năng đăng nhập mà tôi không thể làm với 4.1. Nhưng điều này đã đơn giản hơn nhiều và làm việc như là.
user2662680

20

Bạn có thể sử dụng chức năng Redirect :: dự định . Nó sẽ chuyển hướng người dùng đến URL mà họ đang cố truy cập trước khi bị bộ lọc xác thực bắt gặp. Một URI dự phòng có thể được cung cấp cho phương thức này trong trường hợp định mệnh dự định không có sẵn.

Trong bài đăng nhập / đăng ký:

return Redirect::intended('defaultpageafterlogin');

11

Tôi đã sử dụng điều này trong một thời gian trên mã chọn ngôn ngữ của tôi. Miễn là bạn chỉ cần quay lại chỉ 1 trang là nó hoạt động tốt:

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

Nó không phải là giải pháp mạnh nhất ngoài kia nhưng nó cực dễ và có thể giúp giải một vài câu đố. :)


5
Có trước đó () hoạt động tốt. Nhưng nếu nỗ lực đăng nhập đầu tiên của bạn không thành công (vì vậy trang 'đăng nhập thất bại' trở thành trang trước đó của bạn) và nỗ lực đăng nhập thứ hai thành công thì bạn được chuyển hướng đến trang đăng nhập lại (có thể chuyển hướng bạn đến trang chủ).
Shriganesh Shintre

11

Thay đổi hàm tạo của LoginControllers thành:

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

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

Nó sẽ chuyển hướng bạn quay lại trang TRƯỚC trang đăng nhập (quay lại 2 trang).


Người duy nhất làm việc cho tôi. Nó có nghĩa là tôi có một chuyển hướng khác xảy ra ở đâu đó nhưng ai biết được ở đâu.
Arthur Tarasov

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

điều này sẽ chuyển hướng bạn đến trang mặc định của dự án, tức là trang bắt đầu.


6

Đối với laravel 5. * hãy thử những cái này.

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

hoặc là

return Redirect::intended('/');

5

Ấu trùng 3

Tôi đã tinh chỉnh mã của bạn (Vinícius Fragoso Pinheiro) và đặt đoạn mã sau vào bộ lọc.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');
    }
});

Và sau đó trong AuthControll.php của tôi:

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

Lưu ý rằng 'redirect' dữ liệu phiên được phản xạ nếu có vấn đề xác thực. Điều này giữ cho chuyển hướng nguyên vẹn trong bất kỳ rủi ro đăng nhập nào, nhưng nếu người dùng nhấp vào bất kỳ lúc nào, quá trình đăng nhập tiếp theo sẽ không bị gián đoạn bởi dữ liệu phiên.

Bạn cũng cần phải khởi động lại dữ liệu tại điểm hiển thị biểu mẫu đăng nhập trong của bạn AuthController, nếu không chuỗi bị hỏng:

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

Dành cho Laravel 5.5 và có thể là 5.4

Trong Ứng dụng \ http \ Middleware \ Redirect IfAuthenticated thay đổi redirect('/home')thành redirect()->intended('/home')trong chức năng xử lý:

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

    return $next($request);
}

trong Ứng dụng \ http \ Bộ điều khiển \ Auth \ Đăng nhập Trình điều khiển tạo showLoginForm()chức năng như sau:

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

Bằng cách này, nếu có ý định cho một trang khác, nó sẽ chuyển hướng đến đó nếu không nó sẽ chuyển hướng về nhà.


0

Tôi đang sử dụng cách tiếp cận sau với bộ điều khiển đăng nhập tùy chỉnh và phần mềm trung gian cho Laravel 5.7, nhưng tôi hy vọng nó hoạt động trong bất kỳ phiên bản laravel 5 nào

  • bên trong phần mềm trung gian

    if (Auth::check()){
        return $next($request);
    }
    else{
      return redirect()->guest(route('login'));
    }
  • bên trong phương thức đăng nhập bộ điều khiển

    if (Auth::attempt(['email' => $email, 'password' => $password])) {
    return redirect()->intended('/default');
    }
  • Nếu bạn cần chuyển url có ý định cho phía khách hàng , bạn có thể thử cách sau

       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

Trước tiên, bạn nên biết, cách bạn chuyển hướng người dùng đến tuyến đường 'đăng nhập':

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

Không như thế này:

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

0

Giờ đây, Laravel hỗ trợ tính năng vượt trội này! (Tôi tin từ 5.5 trở về trước).

Thêm một __construct()phương thức cho bạn Controllernhư hiển thị bên dưới:

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

Sau khi đăng nhập, người dùng của bạn sau đó sẽ được chuyển hướng đến trang họ dự định truy cập ban đầu.

Bạn cũng có thể thêm tính năng xác minh email của Laravel theo yêu cầu của logic ứng dụng của bạn:

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

Tài liệu này chứa một ví dụ rất ngắn gọn:

Cũng có thể chọn phương thức của bộ điều khiển mà phần mềm trung gian áp dụng cho bằng cách sử dụng except hoặc onlytùy chọn.

Ví dụ với except:

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

Ví dụ với only:

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

Thêm thông tin về các tùy chọn exceptonlyphần mềm trung gian:


0

nếu bạn đang sử dụng axios hoặc thư viện javascript AJAX khác, bạn có thể muốn truy xuất url và chuyển đến giao diện người dùng

bạn có thể làm điều đó với mã dưới đây

   $default = '/';

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

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

Điều này sẽ trả về một chuỗi định dạng json


0

Trong Laravel 5,8

trong Ứng dụng \ http \ Bộ điều khiển \ Auth \ Đăng nhập Trình điều khiển thêm phương thức sau

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

trong Ứng dụng \ http \ Middleware \ Redirect IfAuthenticated thay thế "return redirect ('/ home');" bằng cách sau

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

-1

Bạn đã thử điều này trong Rout.php của bạn?

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
Vui lòng cung cấp một số bình luận để đi cùng với mã của bạn để cung cấp một số bối cảnh. Cảm ơn
Suever

-1

Đây là giải pháp của tôi cho 5.1. Tôi cần ai đó nhấp vào nút "Thích" trên bài đăng, được chuyển hướng để đăng nhập, sau đó quay lại trang gốc. Nếu họ đã đăng nhập,href nút "Thích" đã bị chặn bằng JavaScript và biến thành yêu cầu AJAX.

Nút này là một cái gì đó như <a href="https://stackoverflow.com/like/931">Like This Post!</a>. /like/931được xử lý bởi một LikeContoder yêu cầu authphần mềm trung gian.

Trong phần mềm xác thực trung gian ( handle()chức năng), hãy thêm một cái gì đó như thế này vào lúc bắt đầu:

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

Thay đổi /auth/loginthành bất cứ điều gì URL của bạn để đăng nhập. Mã này lưu URL của trang gốc trong phiên trừ khi URL là URL đăng nhập. Điều này là bắt buộc vì nó xuất hiện như thể phần mềm trung gian này được gọi hai lần. Tôi không chắc tại sao hoặc nếu đó là sự thật. Nhưng nếu bạn không kiểm tra điều kiện đó, nó sẽ bằng với trang gốc chính xác, và sau đó bằng cách nào đó sẽ có cơ hội /auth/login. Có lẽ có một cách thanh lịch hơn để làm điều này.

Sau đó, trong LikeControllerhoặc bất kỳ bộ điều khiển nào bạn có xử lý URL cho nút được ấn trên trang gốc:

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

Phương pháp này cực kỳ đơn giản, không yêu cầu ghi đè bất kỳ chức năng hiện có nào và hoạt động rất tốt. Có thể có một số cách dễ dàng hơn để Laravel làm điều này, nhưng tôi không chắc nó là gì. Sử dụng intended()hàm không hoạt động trong trường hợp của tôi vì LikeContoder cũng cần biết URL trước đó là gì để chuyển hướng trở lại. Thực chất hai cấp độ chuyển hướng ngược.


-1

Đối với Laravel 5.2 (phiên bản trước tôi không sử dụng)

Dán mã vào ứng dụng tệp \ http \ Bộ điều khiển \ Auth \ AurhControll.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*/
}

Và nhập không gian tên: use Session;

Nếu bạn chưa thực hiện bất kỳ thay đổi nào đối với ứng dụng tệp \ http \ Bộ điều khiển \ Auth \ AurhControll.php, bạn chỉ có thể thay thế nó bằng tệp từ GitHub


-1

Ấu trùng 5.2

Nếu bạn đang sử dụng một Middleware khác như Middleware Admin, bạn có thể đặt phiên cho url. Được dự định bằng cách sử dụng như sau:

Về cơ bản chúng ta cần thiết lập thủ công \Session::put('url.intended', \URL::full());để chuyển hướng.

Thí dụ

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

Khi đăng nhập

Đảm bảo sử dụng thử đăng nhập return \Redirect::intended('default_path');


Đó là những gì redirect()->guest('login')dành cho.
Emile Bergeron

-1

Larvel 5.3 này thực sự hiệu quả với tôi chỉ bằng cách cập nhật LoginControll.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-preingly-page-after-login


-1

Đối với Laravle 5.7, bạn cần thay đổi thành:

Middleware> Redirect IfAuthenticated.php

Thay đổi điều này:

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

        return $next($request);
    }

Về điều này:

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

        return $next($request);
    }

return redirect ('/ yourpath');


mypathgì (người dùng vượt qua để quay lại vấn đề này)
Mostafa Norzade
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.