在laravel中将数组传递给中间件

8

我在一个叫做rolMiddleware的中间件中找到了这个句柄:

public function handle($request, Closure $next, $roles)
{
    //dd($request->user());
    foreach ($roles as $rol) {
        if ($request->user()->getTipoUsuario($request->user()->tipo_usuario_id)->getNombreTipoUsuario() == $rol) {
            return $next($request);
        }
    }
    abort(403, "¡No hay autorizacion!");
}

但是$roles是一个数组,在这里是我使用中间件的路线:

Route::get('/mid', ['middleware' => 'roles:super admin', function () {
    return "done";
}]);

我得到的错误信息是:

ErrorException in RolMiddleware.php line 22:
Invalid argument supplied for foreach()

你可能认为我不需要一个数组,因为我只在超级管理员中使用它,在那条路线上,我只需要超级管理员,但有些路线可以供超级管理员和区域管理员使用。
6个回答

28
在Laravel中,您可以使用逗号,将要传递给中间件的参数分开,如下所示:
Route::get('/mid', ['middleware' => 'roles:super,admin', function () {
//                                              ^ note this
    return "done";
}]);

请注意,这不会将参数作为数组发送,因此您无法循环遍历 $roles,除非您将传递的参数用作省略参数,如下所示:

public function handle($request, Closure $next, ...$roles)

相反,您需要为每个角色使用单个参数:

public function handle($request, Closure $next, $role1, $role2) // .... and so on

5
省略号参数就是我需要的。$roles会变成一个数组。非常感谢。 - Christhofer Natalius

4

路由:

Route::get('/access', ['middleware' => 'hasroles:super,admin', function () {
}]);

传递一个参数来检查用户是否具有创建权限。
Route::middleware('admin')->namespace('Admin')->prefix('admin')->group(function(){
    Route::get('/home', 'MainController@getIndex')->name('admin.index')->middleware("hasrole:create");

中间件:

1. 使用参数

public function handle($request, Closure $next, $parm1, $parm2){}

2.使用可变参数

public function handle($request, Closure $next, $parm1, $parm2){}
public function handle($request, Closure $next, ...$parm1){}

双向中间件使用

1: 注册routeMiddleware

// Within App\Http\Kernel Class...
protected $routeMiddleware = [
    'hasrole' => \Illuminate\Auth\Middleware\HasRole::class,

使用:

Route::get('admin/profile', function () {
})->middleware('hasrole'); 

2: 未在 routeMiddleware 中注册

使用方法:

use App\Http\Middleware\HasRole;

Route::get('admin/profile', function () {
    //
})->middleware(HasRole::class);

3

将参数以字符串形式发送,例如:

Route::prefix('panel')->middleware('auth:admin|editor')->group(function (){
    Route::get('/', [SiteController::class, 'index'])->name('site.index');
}

在中间件中编写代码,将该字符串识别为数组

if (in_array(Auth::user()->rule, explode('|', $access))) {
   return $next($request);
} else {
   return redirect()->route('site.denied');
}

0

您可以在中间件中使用explode函数将字符串转换为数组

控制器

public function __construct()
{
    $this->middleware('RoleCheck:admin|user')->except(['index', 'show']);
}

中间件:

public function handle(Request $request, Closure $next, $roles)
{   
    $user = Auth::user();
    $roles = explode("|", $roles); // convert $roles to array
    foreach ($roles as $role) {
        if ($user->hasRole($role))
            return $next($request);
    }

    return redirect('login');
}

0

我不是很明白你的函数具体做什么,但你可以尝试像这样:

public function handle($request, Closure $next, $roles)
{
    if(is_array($roles)){
        //dd($request->user());
        foreach ($roles as $rol) {
            if ($request->user()->getTipoUsuario($request->user()->tipo_usuario_id)->getNombreTipoUsuario() == $rol) {
                return $next($request);
            }
        }
    }else{
        if($request->user()->getTipoUsuario($request->user()->tipo_usuario_id)->getNombreTipoUsuario() == $roles)
            return $next($request);
    }
    abort(403, "¡No hay autorizacion!");
}

0

在中间件文件的末尾,你应该始终使用return $next($request);... 这些示例中有一些没有这样做。

以下是你的路由将会是这样的(web.php 文件):

Route::middleware('auth')->group(function () {
Route::middleware('CheckRole:super-admin')->group(function () {
//super-admin only routes here
});

Route::middleware('CheckRole:user')->group(function () {
//user only routes here
});
});

要在上面的代码中添加更多角色,只需将CheckRole:super-admin,user放在逗号后面,以便为特定组继续添加角色。
下面的中间件将自动阻止没有权限的任何人进入上面指定的区域,只有在用户登录时才能进入。
请确保将下面的中间件添加到:
App\Http\Kernel.php

在`protected $middlewareAliases = [`下面添加以下代码行:
'CheckRole' => \App\Http\Middleware\CheckRole::class,

您的中间件将是:
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

class CheckRole
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     */
    public function handle(Request $request, Closure $next, ...$roles): Response
    {
        if ($request->user()) {

            $userRole = Auth::user()->role->value('name');

            if (! in_array($userRole, $roles)) {
                
                abort(403, 'Your account permissions do not allow access to the requested page');

            }

        }

        return $next($request);
    }
}

这假设您每个用户只有一个角色。如果一个用户有多个角色,那么在中间件代码中需要进行不同的检查。
如果您有多个用户拥有多个角色,您可以使用这个中间件:
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

class CheckRole
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     */
    public function handle(Request $request, Closure $next, ...$roles): Response
    {
        if ($request->user()) {

            $userRoles = Auth::user()->roles
                ->pluck('name')
                ->toArray();

            if (! array_intersect($userRoles, $roles)) {
                
                abort(403, 'Your account permissions do not allow access to the requested page');

            }

        }

        return $next($request);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接