Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Laravel用户能力_Php_Laravel_Laravel 5.1 - Fatal编程技术网

Php Laravel用户能力

Php Laravel用户能力,php,laravel,laravel-5.1,Php,Laravel,Laravel 5.1,在Laravel中,您可以轻松地连接到它们,然后根据用户的请求执行不同的操作: $gate->define('update-post', function ($user, $post) { return $user->id === $post->user_id; }); 但是几乎我所有定义的能力都包含这一部分$user->id====$model->user\u id。我不喜欢它,因为它是一种反复重复的条件,我认为它可能更抽象 我定义的大多数能力都是根据更新/删除记录

在Laravel中,您可以轻松地连接到它们,然后根据用户的请求执行不同的操作:

$gate->define('update-post', function ($user, $post) {
    return $user->id === $post->user_id;
});
但是几乎我所有定义的能力都包含这一部分
$user->id====$model->user\u id
。我不喜欢它,因为它是一种反复重复的条件,我认为它可能更抽象

我定义的大多数能力都是根据更新/删除记录来定义的,因此,如果我可以将全局条件应用于所有记录,或者如果可以有一个组能力定义,这与我们在路由中所做的类似,那就更好了


有什么解决办法吗?我真的很喜欢干的。

我想你可以用中间产品

只需制作一个管理中间件,并在routes和routes组中使用它

您的项目上没有安全漏洞(删除、创建和…操作),因为Laravel有csrf令牌

您也可以使用函数

还有一个重要的提示:

如果您没有在策略类上定义相应的函数并在控制器上调用它
$this->authorize($post)
,则将抛出
未经授权的操作
错误,除非
before()
方法
返回
s
true

例如,在
Dashboard\PostsController
上调用
$this->authorize

public function edit($id)
{
    $post = Post::find($id)->first();
    $this->authorize($post);
    return view('dashboard.post')->with(compact('post'));
}
如果我们定义了一个后策略类:

class PostPolicy
{
    use HandlesAuthorization;

    public function before($user, $ability)
    {
        return $user->is_admin;
    }
}
如果用户是管理员,他/她可以编辑帖子,因为我们在
before()中返回
ed
true
方法,尽管没有同名的方法(与
PostsController中的
edit
方法相同)

事实上,Laravel将检查
策略类
上的before方法方法。如果在返回之前
null
将检查控制器方法上是否有同名的对应方法,如果未找到此方法,则用户无法执行操作


谢谢拉威尔为我们干杯!♥

将此函数添加到AuthServiceProvider

    public function defineAbilities(array $abilities, $gate)
    {
        foreach($abilities as $name => $model){
            $gate->define($name, function ($user, $model){
                return $user->id === ${$model}->user_id;
            });
        }
    }
然后是内部引导方法

$this->defineAbilities(['ability1' => 'model1', 'ability2' => 'model2'], $gate);

我仔细检查了你的问题,但我没有找到“简单”的方法

相反,我可能会这样做:

<?php


namespace App\Policies;

 use App\User;
 use App\Post;

trait CheckOwnership {
    protected function checkOwnership($user, $model) {
        $owned = $user->id === $model->user_id;
        if ($owned === false)
             throw new NotOwnedException;
    }    
 }

 class PostPolicy
 {

     use CheckOwnership;

    public function update(User $user, Post $post)
    {
         try {
             $this->checkOwnership($user, $post);
             //continue other checks
         } catch (NotOwnedException $ex) {
             return false;
         } 
    }
 }

您可以定义另一个函数并在匿名函数中调用它。这将允许您在一个中心位置拥有常用代码,同时仍然允许任何特定于资源的逻辑

将此函数添加到
AuthServiceProvider
类:

public function userCheck(User $user, $target)
{
    // do the user id check
    $result = isset($target->user_id) && isset($user) && $user->id === $target->user_id;
    return $result;
}
您的代码,已修改:

$gate->define('update-post', function ($user, $post) {
    // call the function
    $result = $this->userCheck($user, $post);
    // do some kind of 'update-post' specific check
    return $result/* && some_bool_statement*/;
});

Laravel的一切都是可扩展的,这是其服务提供商的力量所在

您可以将
Gate
对象扩展为
MyCustomGate
对象,并在该对象中执行任何操作。下面是一个例子:

MyCustomGate.php

class MyCustomGate extends \Illuminate\Auth\Access\Gate
{
    protected $hasOwnershipVerification = [];

    /**
     * Define a new ability.
     *
     * @param  string  $ability
     * @param  callable|string  $callback
     * @return $this
     *
     * @throws \InvalidArgumentException
     */
    public function defineWithOwnership($ability, $callback, $foreignUserIdKey = "user_id")
    {
        // We will add this 
        $this->hasOwnershipVerification[$ability] = $foreignUserIdKey;

        return $this->define($ability, $callback);
    }

    /**
     * Resolve and call the appropriate authorization callback.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @param  string  $ability
     * @param  array  $arguments
     * @return bool
     */
    protected function callAuthCallback($user, $ability, array $arguments)
    {
        $callback = $this->resolveAuthCallback(
            $user, $ability, $arguments
        );

        // We will assume that the model is ALWAYS the first key
        $model = is_array($arguments) ? $arguments[0] : $arguments;

        return $this->checkDirectOwnership($ability, $user, $model) && call_user_func_array(
            $callback, array_merge([$user], $arguments)
        );
    }

    /**
     * Check if the user owns a model.
     *
     * @param  string  $ability
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return bool
     */
    protected function checkDirectOwnership($ability, $user, $model)
    {
        if(!isset($this->hasOwnershipVerification[$ability])) {
            return true
        }

        $userIdKey = $this->hasOwnershipVerification[$ability];

        // getAuthIdentifier() is just ->id, but it's better in case the pk of a user is different that id
        return $user->getAuthIdentifier() == $model->{$userIdKey};
    }
}
然后,您必须告诉Laravel使用您的门,而不是默认的门。您可以在
AuthServiceProvider
中执行此操作(假设它正在扩展
illighted\Auth\AuthServiceProvider
,只需添加以下方法

AuthServiceProvider

/**
 * Register the access gate service.
 *
 * @return void
 */
protected function registerAccessGate()
{
    $this->app->singleton(\Illuminate\Contracts\Auth\Access\Gate::class, function ($app) {
        return new MyCustomGate($app, function () use ($app) {
            return $app['auth']->user();
        });
    });
}
这样,您可以使用
definethownership()
方法而不是
define()
来定义能力。对于不需要所有权验证的能力,您仍然可以使用
define()
。还有第三个参数
definethownership()
接受它,即
$foreignUserIdKey
;用于模型具有不同用户id字段的情况


注意:我在运行中编写了代码,没有尝试,它可能有错误,但你明白了。

谢谢,但我没有说我的能力只返回一个
$user->id===$model->user\u id
结果。我说它有这个部分,所以它可能像
$user->id==$post->user\u id&$post->status==0
。谢谢你,蓝色。这是一个nice和clean方法,但我能从中得到的只是一个错误,
无法解决的依赖项解析[Parameter#1[callable$userResolver]]类中的illights\Auth\Access\Gate
我不确定,但我认为自定义重写的
registerAccessGate()
方法未被调用。好的,您的
AuthServiceProvider
是否扩展了Laravel的
AuthServiceProvider
?是否使用自定义的
register()
方法?另一种注册方法是将函数重命名为其他函数,然后在
parent::register()之后调用该函数
在您的
register()
方法中。完整的异常堆栈将非常有用(忽略任何敏感信息)。您可以使用粘贴箱并将其链接到此处。默认情况下,My
AuthServiceProvider
类扩展了
Illumb\Foundation\Support\Providers\AuthServiceProvider
。我没有使用自定义的
register()
方法在我的
AuthServiceProvider
中,但正如您提供的那样,我编写了一个
public register();
并调用了
parent::register()
和重命名的
registerAccessGate()形式
方法。但我收到了与我上面评论的错误完全相同的错误。我粘贴了相关的laravel.log部分。Sliphon我遇到了一件奇怪的事情:
define
的第二个参数应该是
callable
类型。有什么解决方法吗?虹吸似乎是
$user
$post
作为
userCheck()
的第一个和第二个参数不会传递给函数:
未定义变量:user
如果您可以修改您的答案以获得一个有效的解决方案,那么我将毫不犹豫地奖励另一个奖励。我已将我的答案更新为更优雅的答案。似乎闭包会使代码变得不必要的复杂。您需要做的是简单地使用一个简单的助手函数来整合逻辑。