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

天涯浪子 提交于 2019-11-26 21:33:53

问题


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_check:Normal_User','role_check:Admin']], function() {
        Route::get('/user/{user_id}', array('uses' => 'UserController@showUserDashboard', 'as' => 'showUserDashboard'));
    });

This route can be accessed by either Admin or Normal_user. But in this middleware configuration, user is required to be both Admin and Normal_User. How can I add OR condition in middleware parameter passing? Or is there any other method to give permission?

The following is my middleware

public function handle($request, Closure $next, $role)
    {
        if ($role != Auth::user()->user_role->role ) {
            if ($request->ajax() || $request->wantsJson()) {
                return response('Unauthorized.', 401);
            } else {
                return response('Unauthorized.', 401);
            }
        }
        return $next($request);
    }

Can anyone please reply?


回答1:


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".




回答2:


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.




回答3:


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



回答4:


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



回答5:


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


来源:https://stackoverflow.com/questions/38712282/how-to-pass-multiple-parameters-to-middleware-with-or-condition-in-laravel-5-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!