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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 15:17:14  来源:igfitidea点击:

Laravel policy always false

phplaravellaravel-5laravel-5.4

提问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 $useras a parameter in the policy function. So the user to be viewed is never passed in the authorizeResourcemethod.

一切正常。当我$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 profilefunction 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 useror current userand second parameter is $subject, Since policies organize authorization logic around models.

仔细看策略视图方法,第一个参数是authenticated userorcurrent 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 )。

Laravel Docs for Authorization/Policies

授权/政策的 Laravel 文档

回答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 authorizeResourcemethod in the construct, it would be necessary to implement the authorizationmethod for each resource action in order to protect the controller.

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