Laravel 5.3 Login redirect to different pages for

2019-01-19 03:56发布

问题:

I have Laravel 5.3 with three different types of users. I want them to be redirected to different dashboard pages after logging in. For example:

user -> login -> user-dashboard

admin -> login -> admin-dashboard

I have created a middleware called CheckRole:

public function handle($request, Closure $next)
{
    if($request->user() === null) {
    return response("Insufficient Permissions" , 401);
    }
    $actions = $request->route()->getAction();
    $roles = isset($actions['roles']) ? $actions['roles'] : null;

    if($request->user()->hasAnyRole($roles) || !$roles) {
            return $next($request);
        }
    return response("Insufficient Permissions" , 401);

}

Routes

Route::group(['middleware' => ['auth','roles'], 'roles' => 'Admin'],  function () { 
    // Routes here
}

Roles are working perfectly.

Now redirectTo= ''; in the LoginContoller points to one view only. I have checked the documentation and I believe this has something to do with guards which have no explanation on how to set it up.

I have also seen multiauth, but I do not think it is wise to create different tables for different users and hence looking for an alternate answer.

Any Suggestion would be appreciated.

My tables are like:

Table users

id | name | email
---------
1  | John | john@blah.com
2  | Michael | michael@blah.com

Table roles

id | name
---------
1  | Admin
2  | PrivilegedMember
3  | Subscriber

Table user_role

id | user_id | role_id
----------------------
1  |    1    |    1   
2  |    2    |    2

This might be a duplicate of the below question but the answer provided leaves without explaining multiple redirections.

Multiple Authentication in Laravel 5.3

回答1:

Implement an authenticated() method in your LoginController and add the redirection logic there:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    use AuthenticatesUsers;

    // ...

    /**
     * The user has been authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  mixed  $user
     *
     * @return mixed
     */
    protected function authenticated(Request $request, $user)
    {
        if($user->hasRole('Admin')) {
            return redirect()->intended('admin');
        } elseif ($user->hasRole('PrivilegedMember')) {
            return redirect()->intended('PriviligedMember/index');
        }
    }

    // ...
}

The method is called after the user is authenticated. See the last two lines of sendLoginResponse:

/**
 * Send the response after the user was authenticated.
 *
 * @param  \Illuminate\Http\Request  $request
 *
 * @return \Illuminate\Http\Response
 */
protected function sendLoginResponse(Request $request)
{
    $request->session()->regenerate();

    $this->clearLoginAttempts($request);

    return $this->authenticated($request, $this->guard()->user())
            ?: redirect()->intended($this->redirectPath());
}

So it's a perfect candidate for such logics.

One other note on your own answer, the AuthenticatesUser is a trait that horizontally extends the LoginController, you can safely override any of its methods in your controller without touching the core files.



回答2:

The best way (that I've found) to do that is using Traits. What are we going to do is bassically the same but less complicated and more structured:

1. Instead of creating two tables, our User Model will have a role field, in my case I'll have: 'admin', 'employee' and 'user'.

2. We are going to create a Traits Folder, in this case it will be placed in App/Http.

3. We are going to create a new file and call it RedirectTrait.php inside that folder with this content:

<?php

namespace App\Http\Traits;   // Or the place where the trait is stored (step 2)

use Illuminate\Http\Request;

trait RedirectTrait
{
 /**
 * Where to redirect users after register/login/reset based in roles.
 *
 * @param \Iluminate\Http\Request  $request
 * @param mixed $user
 * @return mixed
 */
public function RedirectBasedInRole(Request $request, $user) {

  $route = '';

  switch ($user->role) {
    # Admin
    case 'admin':
      $route = '/admin/dashboard/route';  // the admin's route
    break;

    # Employee
    case 'employee':
      $route = '/employee/dashboard/route'; // the employee's route
    break;

    # User
    case 'user':
       $route = '/user/dashboard/route';   // the user's route
      break;

      default: break;
    }

    return redirect()->intended($route);
  }

}

As you can see, we can 'play' with the redirections, but intended is necessary According laravel documentation:

The intended method on the redirector will redirect the user to the URL they were attempting to access before being intercepted by the authentication middleware. A fallback URI may be given to this method in case the intended destination is not available.

4. Finally, we'll place the trait and call it:

  • In the App/Http/Controllers/Auth/LoginController.php file
 use Illuminate\Http\Request;         // Add 

 use App\Http\Traits\RedirectTrait;   // Call the trait

 class LoginController extends Controller
 {
 ...
 use RedirectTrait;  // Use the trait

/**
 * The user has been authenticated.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  mixed  $user
 * @return mixed
 */
  protected function authenticated(Request $request, $user)
  {
    return $this->RedirectBasedInRole($request, $user);
  }

  ...
  }

We're overwriting the 'authenticated' method placed in Illuminate\Foundation\Auth\AuthenticatesUsers (which is empty by the way)

  • We'll do the same in the App/Http/Controllers/Auth/RegisterController.php file, but the method will have a different name naturally:
/**
 * The user has been registered.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  mixed  $user
 * @return mixed
 */
protected function registered(Request $request, $user)
{
    return $this->RedirectBasedInRole($request, $user);
}

We're overwriting the 'redirected' method stored in Illuminate\Foundation\Auth\RegistersUsers, and is empty as well.

5. Enjoy :D

PS. The reset password redirect is another history.



回答3:

It looks like the below solution over rides the process and does the job. But I do not think it is the right way as we are tinkering with Core files. Some body please throw a light on this.

Go to AuthenticatesUser.php trait.

locate SendLoginResponse(Request $request)

Before returning the default path add your conditions.I have changed it to below

protected function sendLoginResponse(Request $request)
{
    $request->session()->regenerate();

    $this->clearLoginAttempts($request);



    if(Auth::User()->hasRole('Admin')) {
        return redirect()->intended('admin');
    } elseif (Auth::User()->hasRole('PrivilegedMember')) {
        return redirect()->intended('PriviligedMember/index');
    }

    return $this->authenticated($request, $this->guard()->user())
            ?: redirect()->intended($this->redirectPath());
}