在VueJs中使用Laravel的Gate/Authorization

Ste*_*man 9 laravel vue.js laravel-5 vuejs2 laravel-5.4

我不确定以前没有处理过这个问题,但是如何在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

VUE:

<button v-if="comment.can_update">Edit</button>
Run Code Online (Sandbox Code Playgroud)

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

Ste*_*man 19

我最终使用Laravel 资源来实现这一目标.

这是一个例子(注意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),
        ];
    }
}
Run Code Online (Sandbox Code Playgroud)

这允许我使用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>
Run Code Online (Sandbox Code Playgroud)

此外,如果用户能够创建资源,我使用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),
            ],
        ];
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 我真的很喜欢这个解决方案,非常优雅 (2认同)

小智 8

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

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

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

<post-component :can-update="{{ $user->can('update', $post) }}"></post-component>
Run Code Online (Sandbox Code Playgroud)

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

  • 检查本文,它在前端https://pineco.de/implementing-laravels-authorization-front-end/中使用Laravel ACL (2认同)