Laravel 自定义权限规则 - 门、策略或自定义代码

问题描述 投票:0回答:2

我有一个正在逐步构建的 API,以包含我的平台的所有重要业务逻辑和行为。我需要允许或禁止某些操作,但不是基于尝试完成操作的用户的身份。我正在尝试确定实现此逻辑的最佳模式。

我的所有操作都是由位于 app/Service 目录中的各种服务类执行的。例如 - EventService 类负责与事件记录相关的所有操作。这里的一个用例可能是,作为对 cancelEvent(Event $event) 的 API 调用的一部分,必须首先进行检查以确保没有人注册到该事件 - 如果他们注册了,这是不允许的。

这里最好的解决方案是什么?在我看来,GatesPolicies更多的是授权特定用户查看他们是否可以执行请求的操作。我是否应该在服务类中构建“制衡”并阻止其中的操作?或者是否可以创建不关心用户记录的策略(然后我可以在其他地方重用),并且可能在控制器级别检查这些策略?或者还有其他我没有想到的模式?我也看到人们将其写入雄辩的模型中,但这对我来说并不是真正合适的地方。

这里也很重要的是,如果遭到拒绝,能够返回信息丰富的响应。例如“此活动无法取消,因为有 2 个用户注册”。这将返回给 api 调用者,然后反馈给最终用户。

有“Laravel 方式”可以做到这一点吗?

laravel permissions authorization
2个回答
1
投票

策略可以作为您所描述的内容的基础,并且将是一种 Laravel 方式(鉴于他们在 授权文档 中说了这么多)。尽管它们是通过用户上下文调用的,但不需要在策略内部使用。我认为对您的案例有价值的政策的一些好处:

  • 您有一个可用于授权给定操作的定义。
  • Laravel 为您提供了一些方便的方法来获取给定用户和模型的这些策略。
  • 您可以为策略查询提供其他上下文。

我认为第三点可能是您如何获取有关政策失败原因的详细信息。尽管我非常不愿意通过引用传递,但这可能值得例外,以便使用策略框架并获取原因上下文。

这是一个草图:

some.blade.php

@can('doSomething', $someModel)
  You can do the thing.
@else
  Sorry, you cannot do the thing.
@endcan

Http/Controllers/SomeController.php

public function doAction() {
    $reason = null;
    if (auth()->user()->can('doSomething', $someModel, $reason)) {
        return 'Done!';
    } else {
        return 'Not done because ' . $reason
    }
}
class SomeModelPolicy
{
    use HandlesAuthorization;

    public function doSomething(User $user, SomeModel $someModel, string &$reason = null): bool
    {
        if ($someModel->hasSomeState()) {
            return true;
        } else {
            $reason = 'SomeModel does not have some state';
            return false; 
        }
    }
}

需要考虑的一件事是,您仍然需要正在验证的规则的定义,例如我的

$someModel->hasSomeState()
,并且您可能希望将它们封装在模型上,以便调用单个、清晰的业务规则(尽管是一个操作)可能需要检查多个规则)。这有点像“瘦控制器,胖模型”的想法。瘦身政策也能起到同样的作用。


0
投票

这是基于用例的快速指南:

  • 在没有模型的情况下对控制器操作或视图级授权进行单一操作检查:使用 Gate
  • 模型级授权或者封装模型的逻辑授权:使用Policy
  • 复杂、多模型逻辑或进入控制器之前进行过滤:使用中间件

Authz=授权=权限

© www.soinside.com 2019 - 2024. All rights reserved.