How to pass multiple parameters to middleware with OR condition in Laravel 5.2

后端 未结 6 1536
误落风尘
误落风尘 2020-12-06 00:48

I am trying to set permission to access an action to two different user roles Admin, Normal_User as shown below.

Route::group([\'middleware\' => [\'role_c         


        
相关标签:
6条回答
  • 2020-12-06 01:07

    Instead of adding multiple arguments to your handle method and having to update it every time you add a new role to your application, you can make it dynamic.

    Middleware

     /**
     * Handle an incoming request.
     *
     * @param $request
     * @param Closure $next
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function handle($request, Closure $next) {
    
        $roles = array_slice(func_get_args(), 2); // [default, admin, manager]
    
        foreach ($roles as $role) {
    
            try {
    
                Role::whereName($role)->firstOrFail(); // make sure we got a "real" role
    
                if (Auth::user()->hasRole($role)) {
                    return $next($request);
                }
    
            } catch (ModelNotFoundException $exception) {
    
                dd('Could not find role ' . $role);
    
            }
        }
    
        Flash::warning('Access Denied', 'You are not authorized to view that content.'); // custom flash class
    
        return redirect('/');
    }
    

    Route

    Route::group(['middleware' => ['role_check:default,admin,manager']], function() {
        Route::get('/user/{user_id}', array('uses' => 'UserController@showUserDashboard', 'as' => 'showUserDashboard'));
    });
    

    This will check if the authenticated user has at least one of the roles provided and if so, passes the request to the next middleware stack. Of course the hasRole() method and the roles themselves will need to be implemented by you.

    0 讨论(0)
  • 2020-12-06 01:08
                //please take note there must be space between ... $roles
    
            //on your route make sure there is no space in between the roles 
            'checkRole:staff,admin'
    
            public function handle($request, Closure $next, ... $roles)
            {
            foreach($roles as $role){
            if ($request->user()->hasRole($role)){
            return $next($request);
            }
            }
            abort(404);
            }
    
            you can try this out also 
    
    
            Route::group(['middleware' => 'role:webdev|admin'], function () {
            });
            public function handle($request, Closure $next, $role)
    
            {
            $roles = collect(explode('|',$role));
            if (! $request->user()->hasRole($roles)) {
            abort(404, 'No Way');
            }
            return $next($request);
            }
    
    0 讨论(0)
  • 2020-12-06 01:11

    To add multiple parameters, you need to seperate them with a comma:

    Route::group(['middleware' => ['role_check:Normal_User,Admin']], function() {
            Route::get('/user/{user_id}', array('uses' => 'UserController@showUserDashboard', 'as' => 'showUserDashboard'));
        });
    

    Then you have access them to in your middleware like so:

    public function handle($request, Closure $next, $role1, $role2) {..}
    

    The logic from there is up to you to implement, there is no automatic way to say "OR".

    0 讨论(0)
  • 2020-12-06 01:14

    In the middleware class

    <?php
    
     namespace App\Http\Middleware;
    
     use Closure;
     use function abort;
     use function array_flip;
     use function array_key_exists;
     use function array_slice;
     use function func_get_args;
    
     class MustBeOFUserType
     {
         /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request $request
         * @param  \Closure $next
         * @return mixed
         */
         public function handle($request, Closure $next)
         {
            $roles = array_slice(func_get_args(), 2);  // ['admin', 'author']
    
            //flip $roles to get ['admin' => 0, 'author' => 1];
            if (!auth()->guest() && array_key_exists(auth()->user()->role->name, array_flip($roles))) {
    
              return $next($request);
            }
            abort(423, 'Sorry you are not authrized !');
    
         }
       }
    

    in the web.php OR route file

    Route::get('/usertype', function() {
    
       return response(['Accessed'], 200);
    })->middleware([
        'App\Http\Middleware\MustBeOFUserType:admin,author'
    ]);
    

    Remember space on ':admin,author' like ':admin, author' will result into errors

    For sanity check and if your a TDD person like I am use this to test the middleware

    <?php
    
     namespace Tests\Feature;
    
     use App\User;
     use Illuminate\Foundation\Testing\RefreshDatabase;
     use Tests\TestCase;
     use function factory;
    
     class MustBeOFUserTypeTest extends TestCase
     {
        use RefreshDatabase;
    
        /** @test * */
        public function it_accepts_the_admin()
        {
           $this->signIn(factory(User::class)->states('administrator')->create());
    
           $this->get('/usertype')->assertStatus(200);
         }
    
         /** @test * */
         public function it_rejects_normal_users()
         {
           $this->signIn();
    
           $this->get('/usertype')->assertStatus(423);
          }
    
          /** @test **/
          public function it_accepts_authors()
          {
    
            $this->signIn(factory(User::class)->states('author')->create());
    
            $this->get('/usertype')->assertStatus(200);
           }
    
           public function signIn($user = null)
           {
    
                $u = $user ?: factory('App\User')->states('normal')->create();
    
                 $this->be($u);
    
                 return $this;
                }
           } 
    
    0 讨论(0)
  • 2020-12-06 01:15

    You can use the 3 dot (...) syntax in PHP 5.6+

    Your middleware's handle function

    public function handle($request, Closure $next, ...$roles)
    {
        foreach($roles as $role){
            if ($request->user()->hasRole($role)){
                return $next($request);
            }
        }
        abort(404);
    }
    
    0 讨论(0)
  • 2020-12-06 01:21

    This super easy dynamic implementation might come handy for someone, in your middlewear file checkRole.php:

    public function handle($request, Closure $next, ... $roles)
    {
        $found = false;
        foreach ($roles as $role) {
            if (session('type') == $role) {
                $found = true; break;
            }
        }
    
        if (!$found) {
            return back()->with('error','Access denied!');
        }
    
        return $next($request);
    }
    

    and call the middlewear from web.php with as much parameter you need to pass:

    Route::get('/approve',  'aController@approve')  ->middleware('roles:admin');
    Route::get('/dashboard','bController@dashboard')->middleware('roles:admin,user');
    

    also don't forget to modify the middlewear key name in your Kernel.php:

    'roles' => \App\Http\Middleware\checkRole::class,
    
    0 讨论(0)
提交回复
热议问题