如何将多个字符串变量传递给Laravel Gate

时间:2019-02-20 19:06:53

标签: laravel

我有一个“安全”服务,我想逐渐移至Laravel Gate,因此我可以从Laravel在APP其余部分中提供的帮助方法中受益。

我现在对门的定义如下:

Gate::define('denja', function($user, $module, $permission) {
    // validation of access to $module and $permission goes here
});

这在我做的时候很好

$user->can('denja', ['accounting', 'invoice.create']);```

例如,但我看不到如何定义中间件以使其正常运行...

Route::post( '/accounting/invoices', 'InvoiceController@create')
  ->middleware("can:denja,accounting,invoice.create");```

从中间件传递这些参数似乎是不可能的-页面现在总是返回403 ... 关于如何将这些参数正确地从中间件传递给Gate的任何想法?我认为这实际上是参数的问题;即使在定义的门中有dd(),我也得到了403

我知道我有点“滥用”系统,但是由于我们现有的服务基本上希望该模块下的用户,模块和权限,所以我现在只想委托给该服务... < / p>

2 个答案:

答案 0 :(得分:1)

使用can中间件时:

  

第一个是我们希望授权的操作的名称,第二个是我们希望传递给策略方法或Model类路径的route参数。 documentation

例如:

Route::put('/post/{postId}', function (Post $post) {
    // The current user may update the post...
})->middleware('can:update,postId');

OR

Route::post('/post', function () {
    // The current user may create posts...
})->middleware('can:create,App\Post');

在您的情况下:

Route::post( '/accounting/invoices', 'InvoiceController@create')
  ->middleware("can:denja,accounting,invoice.create");

缺少基本参数签名,因为没有名称为accountinginvoice.create的路由参数,也没有类。

解决方案:

从路由声明中删除中间件:

Route::post( '/accounting/invoices', 'InvoiceController@create');

您可以在控制器中使用can()方法:

public function create(Request $request){

    // Initialize $model and $permissions 
    // as per your business logic
    if(!$request->user()->can('denja', $module, $permission){
        abort(403);
    }
    // continue your logic for authorised user
}

即使以上解决方案可行,但如果您有更多的授权规则,最好创建一个policy类。

答案 1 :(得分:1)

我遇到了同样的问题,所以我做了一些“ can”中间件的研究(哪个映射到Illuminate\Auth\Middleware\Authorize

在课堂上,我们将看到以下代码

 /**
     * Get the model to authorize.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  string  $model
     * @return \Illuminate\Database\Eloquent\Model|string
     */
    protected function getModel($request, $model)
    {
        if ($this->isClassName($model)) {
            return trim($model);
        } else {
            return $request->route($model, null) ?:
                ((preg_match("/^['\"](.*)['\"]$/", trim($model), $matches)) ? $matches[1] : null);
        }
    }

这意味着...
如果传入的字符串是一个类名,则返回该类名
如果不是类名,则...
1)尝试从路线获取它,然后返回路线参数 2)尝试通过正则表达式"/^['\"](.*)['\"]$/"从字符串中获取模型

现在让我们说我们有一个中间件调用 $this->middleware(sprintf("can:create,%s,%s", User::class, Role::SUPPORT));
由于Role::SUPPORT与正则表达式不匹配,因此无法使用
要匹配它,我们只需要将Role::SUPPORT放在引号中即可。
注意第二个%s附近的“'” $this->middleware(sprintf("can:create,%s,'%s'", User::class, Role::SUPPORT));

要具体回答您的问题,请引用您的字符串

Route::post('/accounting/invoices', 'InvoiceController@create')
  ->middleware("can:'denja','accounting','invoice.create'");