繁体   English   中英

Laravel 资源策略始终为 false

[英]Laravel resource policy always false

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

用户策略.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

用户控制器.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 ) );
}

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

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

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

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

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

  $this->authorize('view',$user);

一切正常。 当我在策略函数中添加$user作为参数时,我一定错过了这一部分。 所以要查看的用户永远不会传入authorizeResource方法。

感谢大家花时间帮助我。

当你添加

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

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

之后它应该工作

对于用户查看他们自己的个人资料,这里只是一种不同的方法。

首先,我将为此创建一条路线

Route::group(['middleware' => 'auth'], function() {
    Route::get('profile', 'UserController@profile');
});

然后在profile功能中我做

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

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

现在,如果您想允许某些用户查看其他用户的个人资料,则可以使用 Policy。 为什么? 因为我认为用户应该始终能够查看他们自己的个人资料。 但并非所有用户都应该查看其他用户的个人资料。

解决方案:

将第二个参数从@can( 'view', $user )更改为@can( 'view', $subject ) ,它会找到工作。

为什么:

因为你做错了。

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

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

策略是围绕特定模型或资源组织授权逻辑的类。 例如,如果您的应用程序是一个博客,您可能有一个 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 文档

可以使用 authorizeResource 中的 options 参数来转义一个或多个策略方法,除了:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM