在 VueJs 中使用 Laravel 的 Gate/Authorization [英] Using Laravel's Gate / Authorization in VueJs

查看:36
本文介绍了在 VueJs 中使用 Laravel 的 Gate/Authorization的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不确定以前没有处理过这个问题,但是我如何使用 VueJs 并在 Vue 模板中授权操作?

I'm not sure how this hasn't been dealt with before, but how do I go about using VueJs and authorizing actions in Vue template?

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

If I'm using Laravel's blade, this is easy (using @can directive), but there's no documentation or any way to perform this in Vue after searching for hours on Google.

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

Now, I know I can simply load the users permissions into an array / JSON object inside the view, but there seems to be no way of displaying / hiding actions in Vue templates using Laravel's gate methods to determine if the user is allowed to perform the action on a specific record.

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

For example, there's a list of comments, but the user must own the comment to be able to see the 'edit' button.

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

The thing is, if I implement the logic in Vue, I'd be duplicating authorization logic throughout my entire backend and frontend for this.

使用 Laravel 的策略,我能够对特定操作执行复杂的授权.但我对如何在 Vue 中实施该政策感到困惑.

Using Laravel's policy's, I'm able to perform complex authorization of specific actions. But I'm stumped as to how I would implement the policy in Vue.

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

There's also more complex scenarios, such as if a user that has an admin role is browsing comments, they should be able to edit it even if they don't own the comment.

有人对这种场景有什么建议吗?

Does anyone have any suggestions for this type of scenario?

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

Now I could add an attribute accessor to my models, for example:

型号:

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

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

Vue:

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

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

But this seems like I'm again duplicating logic that already exists inside my policies.

推荐答案

我最终使用了 Laravel resources 来实现这一点.

I ended up using Laravel resources to accomplish this.

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

Here's an example (notice the can array key):

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 模板中使用简单的布尔逻辑来控制前端的访问,而不是在前端复制实际的权限逻辑:

This allowed me to control access on the front-end using simple boolean logic in Vue templates, rather than duplicating actual permission logic on the front-end as well:

<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 资源集合能够应用权限:

Also, I used Laravel resource collections to be able to apply permissions if the user is able to create a resource:

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 控制器中:

Then in my API controller:

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

    return new TicketCollection($tickets);
}

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

    return new TicketResource($ticket);
}

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

This allowed me to validate if the currently authenticated user has access to be able to create the resource that is being listed, since we won't have an actual resource to validate on, we can do this on the returned collection since it relates to it entirely.

在我看来,实现此模式是管理授权的最简单方法,无需在整个 Vue 应用程序中复制实际授权逻辑,也无需使用刀片将权限单独注入组件.

Implementing this pattern seemed to me the simplest way of managing authorization without duplicating the actual authorizing logic throughout my Vue app and using blade to inject permissions into components individually.

如果您的嵌套组件也需要权限,那么将权限注入组件最终会给我带来问题,因为这样您就需要将子组件的权限传递给父组件才能对其进行验证.

Injecting permissions into components eventually lead me to problems if you have nested components that also require permissions, because then you'll need to pass the child components permissions into the parents to be able to validate them.

对于嵌套权限,您可以从父资源返回子资源,用于还包含一个 can 权限数组的关系,因此您可以使用 Vue 轻松循环这些子资源,并使用简单的逻辑来确定用户也可以访问这些内容.

For nested permissions, you can return sub-resources from your parent resource for relationships that also include a can permissions array, so you can easily loop through these using Vue and use simple logic for determining the users access on those as well.

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

This approach was also beneficial so I could cache the permissions for each user via server-side on resources that don't change often.

这篇关于在 VueJs 中使用 Laravel 的 Gate/Authorization的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆