我正在尝试允许用户在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 ) );
}
回报总是“假”。从控制器调用策略也是如此。我哪里出错?
答案 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 user
或current 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)。
答案 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
方法以保护控制器