Laravel 政策总是错误的
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42076895/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel policy always false
提问by sr9yar
I'm trying to allow user to view their own profile in Laravel 5.4.
我试图允许用户在 Laravel 5.4 中查看他们自己的个人资料。
UserPolicy.php
用户策略.php
public function view(User $authUser, $user)
{
return true;
}
registered policy in AuthServiceProvider.php
在 AuthServiceProvider.php 中注册的策略
protected $policies = [
App\Task::class => App\Policies\TaskPolicy::class,
App\User::class => App\Policies\UserPolicy::class
];
Routes
路线
Route::group(['middleware' => 'auth'], function() {
Route::resource('user', 'UserController');
} );
Blade template
刀片模板
@can ( 'view', $user )
// yes
@else
// no
@endcan
UserController.php
用户控制器.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 ) );
}
The return is always 'false'. Same for calling policy form the controller. Where do I go wrong?
返回总是“假”。从控制器调用策略也是如此。我哪里出错了?
回答by sr9yar
Answering my own question feels weird, but I hate it when I come across questions without followups.
回答我自己的问题感觉很奇怪,但是当我遇到没有跟进的问题时,我讨厌它。
So after double checking It turned out that if I remove authorizeResourcefrom the constructor:
所以经过仔细检查后发现,如果我从构造函数中删除authorizeResource:
public function __construct()
{
$this->authorizeResource(User::class);
}
and check for authorization in the controller function:
并检查控制器功能中的授权:
$this->authorize('view',$user);
everything works.
I must've missed this part when I added $user
as a parameter in the policy function. So the user to be viewed is never passed in the authorizeResource
method.
一切正常。当我$user
在策略函数中作为参数添加时,我一定错过了这一部分。所以在authorizeResource
方法中永远不会传递要查看的用户。
Thanks everyone for taking your time to help me.
感谢大家花时间帮助我。
回答by EddyTheDove
Just a different approach here to users viewing their own profile.
只是用户查看自己的个人资料的一种不同方法。
First, I will create a route for that
首先,我将为此创建一条路线
Route::group(['middleware' => 'auth'], function() {
Route::get('profile', 'UserController@profile');
});
Then in the profile
function I do
然后在profile
我做的功能中
public function profile()
{
$user = Auth::user();
return view('profile', compact('user'));
}
This way, user automatically only views their own profile.
这样,用户自动只查看他们自己的个人资料。
Now, if you want to allow some users to view others' profiles, then you can use Policy. Why? Because I think user should ALWAYS be able to view their own profile. But not all users should view other users profiles.
现在,如果您想允许某些用户查看其他用户的个人资料,则可以使用 Policy。为什么?因为我认为用户应该始终能够查看他们自己的个人资料。但并非所有用户都应该查看其他用户的个人资料。
回答by rummykhan
Solution:
解决方案:
Change the second parameter from @can( 'view', $user )
to @can( 'view', $subject )
and it will work find.
将第二个参数从@can( 'view', $user )
to更改为@can( 'view', $subject )
可以找到。
Why:
为什么:
Because you're doing it the wrong way.
因为你做错了。
public function view(User $user, $subject){
return true;
}
Just look carefully the policy view method, first parameter is authenticated user
or current user
and second parameter is $subject
, Since policies organize authorization logic around models.
仔细看策略视图方法,第一个参数是authenticated user
orcurrent user
第二个参数是$subject
,因为策略围绕模型组织授权逻辑。
Policies are classes that organize authorization logic around a particular model or resource. For example, if your application is a blog, you may have a Post model and a corresponding PostPolicy to authorize user actions such as creating or updating posts.
策略是围绕特定模型或资源组织授权逻辑的类。例如,如果您的应用程序是一个博客,您可能有一个 Post 模型和一个相应的 PostPolicy 来授权用户操作,例如创建或更新帖子。
if you want to go further deep inside it.
如果你想更深入地了解它。
https://github.com/laravel/framework/blob/5.3/src/Illuminate/Auth/Access/Gate.php#L353
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);
};
}
See the last line where it is calling the method with $user and $argument( in our case Model ) is passed.
请参阅最后一行,它使用 $user 调用方法,并传递了 $argument(在我们的示例中为 Model )。
回答by Mike_NotGuilty
When you add
当你添加
public function __construct()
{
$this->authorizeResource(User::class);
}
to your Controller, you have to edit all your function signatures to match it to the class e.g. your show signature has to change from public function show($id)
to public function show(User $user)
到您的控制器,您必须编辑所有函数签名以将其与类匹配,例如您的显示签名必须从 更改public function show($id)
为public function show(User $user)
After that it should work
之后它应该工作
回答by Matheus Camara
It's possible to escape one or more policies methods using options parameter at authorizeResource with except:
可以使用 authorizeResource 中的 options 参数来转义一个或多个策略方法,除了:
public function __construct()
{
$this->authorizeResource(User::class, 'user', ['except' => ['view']]);
}
This should be on Laravel's documentation, but it isn't. I discovered this just guessing. I think this way it is a better approach thus, by removing authorizeResource
method in the construct
, it would be necessary to implement the authorization
method for each resource action in order to protect the controller.
这应该在 Laravel 的文档中,但事实并非如此。我发现这只是猜测。我认为这是一种更好的方法,因此,通过删除 中的authorizeResource
方法,construct
有必要authorization
为每个资源操作实现该方法以保护控制器。