在VueJs中使用Laravel的Gate / Authorization

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

我不确定之前是如何处理的,但是如何在Vue模板中使用VueJs和授权操作呢?

如果我使用Laravel的刀片,这很容易(使用@can指令),但是在Google上搜索了几个小时后,没有文档或任何方法可以在Vue中执行此操作。

现在,我知道我可以简单地将用户权限加载到视图中的数组/ JSON对象中,但似乎无法使用Laravel的门方法在Vue模板中显示/隐藏操作,以确定是否允许用户执行对特定记录采取行动。

例如,有一个评论列表,但用户必须拥有评论才能看到“编辑”按钮。

问题是,如果我在Vue中实现逻辑,我将在整个后端和前端复制授权逻辑。

使用Laravel的策略,我能够执行特定操作的复杂授权。但我很难过如何在Vue中实施该政策。

还有更复杂的场景,例如,如果具有admin角色的用户正在浏览评论,即使他们不拥有评论,他们也应该能够编辑它。

有没有人对这种情况有任何建议?

编辑:

现在我可以为我的模型添加属性访问器,例如:

模型:

class Comment extends Model
{
    protected $appends = ['can_update'];

    public function getCanUpdateAttribute()
    {
        return Gate::allows('update', $this);
    }
}

查看:

<button v-if="comment.can_update">Edit</button>

但这似乎我再次复制了我的政策中已经存在的逻辑。

laravel laravel-5 vue.js vuejs2 laravel-5.4
2个回答
14
投票

我最终使用Laravel resources来实现这一目标。

这是一个例子(请注意can数组键):

class Ticket extends Resource
{
    /**
     * The "data" wrapper that should be applied.
     *
     * @var string
     */
    public static $wrap = 'ticket';

    /**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'answer_id' => $this->answer_id,
            'summary' => $this->summary,
            'description' => $this->description,
            'creator' => $this->creator,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
            'reported_at' => $this->reported_at,
            'closed_at' => $this->closed_at,
            'closed' => $this->closed,
            'answered' => $this->answered,
            'can' => $this->permissions(),
        ];
    }

    /**
     * Returns the permissions of the resource.
     *
     * @return array
     */
    protected function permissions()
    {
        return [
            'update' => Gate::allows('update', $this->resource),
            'delete' => Gate::allows('delete', $this->resource),
            'open' => Gate::allows('open', $this->resource),
        ];
    }
}

这允许我使用Vue模板中的简单布尔逻辑来控制前端的访问,而不是在前端复制实际的权限逻辑:

<router-link v-if="ticket.can.update" :to="{name:'tickets.edit', params: {ticketId: ticket.id}}" class="btn btn-sm btn-secondary">
    <i class="fa fa-edit"></i> Edit
</router-link>

此外,如果用户能够创建资源,我使用Laravel资源集合来应用权限:

class TicketCollection extends ResourceCollection
{
    /**
     * The "data" wrapper that should be applied.
     *
     * @var string
     */
    public static $wrap = 'tickets';

    /**
     * Get any additional data that should be returned with the resource array.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return array
     */
    public function with($request)
    {
        return [
            'can' => [
                'create' => Gate::allows('create', Ticket::class),
            ],
        ];
    }
}

然后在我的API控制器中:

public function index()
{
    $tickets = Ticket::paginate(25);

    return new TicketCollection($tickets);
}

public function show(Ticket $ticket)
{
    $ticket->load('media');

    return new TicketResource($ticket);
}

这使我能够验证当前经过身份验证的用户是否有权创建正在列出的资源,因为我们没有实际的资源可以验证,我们可以在返回的集合上执行此操作,因为它与之相关完全。

在我看来,实现这种模式是管理授权的最简单方法,而不会在我的Vue应用程序中复制实际的授权逻辑,并使用刀片将权限单独注入组件。

如果您有嵌套的组件也需要权限,那么将权限注入组件最终会导致我遇到问题,因为这样您就需要将子组件权限传递给父组件才能验证它们。

对于嵌套权限,您可以从父资源返回子资源,以获取也包含can权限数组的关系,这样您就可以使用Vue轻松遍历这些资源,并使用简单的逻辑来确定用户对这些资源的访问权限。

这种方法也很有用,因此我可以通过服务器端在不经常更改的资源上缓存每个用户的权限。


6
投票

目前,如果不将后端代码复制到前端,就无法实现这一目标。

在这一集Fullstack Radio(17:15)中,Jeffrey Way和Adam Wathan谈到了这一点。他们和我有同样的看法,目前他们做的和你做的一样。

他们还谈到了使用道具,如:

<post-component :can-update="{{ $user->can('update', $post) }}"></post-component>

我希望这个答案可以有所帮助。

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