Laravel政策总是错误的

时间:2017-02-06 20:41:00

标签: php laravel laravel-5 laravel-5.4

我正在尝试允许用户在Laravel 5.4中查看自己的个人资料。

UserPolicy.php

public function view(User $authUser, $user)
{ 
 return true;
}

AuthServiceProvider.php中的注册政策

protected $policies = [
    App\Task::class => App\Policies\TaskPolicy::class,
    App\User::class => App\Policies\UserPolicy::class
];

路线

Route::group(['middleware' => 'auth'], function() {
  Route::resource('user', 'UserController');
} );

刀片模板

@can ( 'view', $user )
// yes
@else
// no
@endcan

UserController.php

public function profile()
{
    return $this->show(Auth::user()->id);
}
public function show($id)
{
    $user = User::find($id);
    return view('user.show', array( 'user'=>$user,'data'=>$this->data ) );
}

回报总是“假”。从控制器调用策略也是如此。我哪里出错?

5 个答案:

答案 0 :(得分:4)

回答我自己的问题感觉很奇怪,但是当我遇到没有后续问题的问题时,我讨厌它。

所以经过仔细检查后发现,如果我从构造函数中删除authorizeResource

  public function __construct()
  {
    $this->authorizeResource(User::class);
  }

并检查控制器功能中的授权

  $this->authorize('view',$user);
一切正常。 当我在策略函数中添加$user作为参数时,我肯定错过了这一部分。因此,要查看的用户永远不会通过authorizeResource方法传递。

感谢大家花时间帮助我。

答案 1 :(得分:1)

这是一种不同的方法,用户可以查看自己的个人资料。

首先,我将为该

创建一条路线
Route::group(['middleware' => 'auth'], function() {
    Route::get('profile', 'UserController@profile');
});

然后在profile函数中

public function profile()
{
    $user = Auth::user();
    return view('profile', compact('user'));
}

这样,用户只能自动查看自己的个人资料。

现在,如果您想允许某些用户查看其他用户'配置文件,然后您可以使用策略。为什么?因为我认为用户应该始终能够查看自己的个人资料。但并非所有用户都应该查看其他用户个人资料。

答案 2 :(得分:0)

<强>解决方案:

将第二个参数从@can( 'view', $user )更改为@can( 'view', $subject ),它将起作用。

<强>为什么:

因为你做错了。

public function view(User $user, $subject){ 
 return true;
}

仔细查看策略视图方法,第一个参数是authenticated usercurrent user,第二个参数是$subject,因为策略会围绕模型组织授权逻辑。

  

策略是围绕a组织授权逻辑的类   特定的模型或资源。例如,如果您的应用程序是   博客,您可能有Post模型和相应的PostPolicy   授权用户操作,例如创建或更新帖子。

如果你想进一步深入其中。

https://github.com/laravel/framework/blob/5.3/src/Illuminate/Auth/Access/Gate.php#L353

/**
 * Resolve the callback for a policy check.
 *
 * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
 * @param  string  $ability
 * @param  array  $arguments
 * @return callable
 */
protected function resolvePolicyCallback($user, $ability, array $arguments)
{
    return function () use ($user, $ability, $arguments) {
        $instance = $this->getPolicyFor($arguments[0]);

        // If we receive a non-null result from the before method, we will return it
        // as the final result. This will allow developers to override the checks
        // in the policy to return a result for all rules defined in the class.
        if (method_exists($instance, 'before')) {
            if (! is_null($result = $instance->before($user, $ability, ...$arguments))) {
                return $result;
            }
        }

        if (strpos($ability, '-') !== false) {
            $ability = Str::camel($ability);
        }

        // If the first argument is a string, that means they are passing a class name
        // to the policy. We will remove the first argument from this argument list
        // because the policy already knows what type of models it can authorize.
        if (isset($arguments[0]) && is_string($arguments[0])) {
            array_shift($arguments);
        }

        if (! is_callable([$instance, $ability])) {
            return false;
        }

        return $instance->{$ability}($user, ...$arguments);
    };
}

查看使用$ user调用方法的最后一行,并传递$ argument(在我们的示例中为Model)。

Laravel Docs for Authorization/Policies

答案 3 :(得分:0)

添加时

public function __construct()
{
   $this->authorizeResource(User::class);
}

对于您的控制器,您必须编辑所有函数签名以使其与类匹配,例如您的演出签名必须从public function show($id)更改 到public function show(User $user)

此后它应该工作

答案 4 :(得分:0)

可以使用authorizeResource的options参数来转义一个或多个策略方法,但以下情况除外:

public function __construct()
{
   $this->authorizeResource(User::class, 'user', ['except' => ['view']]);
}

这应该在Laravel的文档中,但事实并非如此。我发现这只是猜测。我认为这样是一种更好的方法,因此,通过删除authorizeResource中的construct方法,有必要为每个资源操作实现authorization方法以保护控制器