基于Vue.js开发的应用程序如何管理用户权限

在前端应用程序的认证过程中,我们常常想根据自己的角色指派来做些改变,使得一些内容是用户可见,另外一些不可见。例如,guest用户可以看到一个帖子,但只有注册用户或管理员才可以看到一个按钮来编辑该邮件。

在前端应用程序中权限管理可能十分的凌乱。你可能以前也写过这样的代码:

if (user.type === ADMIN || user.auth && post.owner === user.id ) {

...

}
复制代码

作为替代,有一个整洁的小类库CASL可以非常简单的帮助你来管理用户权限。一旦你用CASL定义了你的权限管理,并且激活的一个用户,你就可以把上述的例子改变成这样:

if (abilities.can('update', 'Post')) {

...

}

复制代码

在这篇文章中,我将演示如何在一个基于Vue.js和CASL的前端应用程序中管理权限。

基于Vue.js开发的应用程序如何管理用户权限?

CASL语言快速入门

它允许您定义一组规则,可以限制资源到给定的用户,即确定是否允许他们访问这些资源。

例如,使用规则可以是用户可以在一个给定的资源或实体(例如,一个帖子,评论,文章等)进行CRUD操作(创建、读取、更新和删除)。

假设我们有一个分类广告网站,有简单的“销售”职位。这个应用程序的一套显而易见的规则是:

guest用户可以查看任何帖子。

管理用户可以查看任何帖子,并可以更新或删除一个帖子。

在CASL,我们使用AbilityBuilder来定义规则。一个新规则是用一个可以调用的方法来创建的,例如:

const { AbilityBuilder } = require('casl');

export function(type) {

AbilityBuilder.define(can => {

switch(type) {

case 'guest':

can('read', 'Post');

break;

case 'admin':

can('read', 'Post');

can(['update', 'delete'], 'Post');

break;

// Add more roles here

}

}

};

复制代码

现在你可以根据你定义的规则检查你的应用程序,例如:

import defineAbilitiesFor from './abilities';

let currentUser = {

id: 999,

name: "Julie"

type: "registered",

};

let abilities = defineAbilitiesFor(currentUser.type);

Vue.component({

template: `<div v-if="showPost"><div>

<div v-else>Please log in</div>

`,

props: [ 'post' ],

computed: {

showPost() {

return abilities.can('read', 'Post');

}

}

});

复制代码

你可以找到更多关于CASL的官方文档(https://stalniy.github.io/casl/)。

演示项目

作为演示,我制作了一个简单的服务器/客户端应用程序,其中显示了分类广告帖子。此应用程序的权限规则是:用户可以阅读任何文章或创建新的帖子,但只能更新或删除由他们自己创建的职位的帖子。

我用vue.js与CASL使这些规则易于实现并可以支持一定规模的访问,以防未来增加其他实体或操作。

现在我将介绍这个应用程序的设置步骤。如果你想看到完整的代码,那么你可以访问一下这个GitHub的repo看看(https://github.com/anthonygore/vue-casl-demo)。

定义用户权限

让我们在resources/ability.js文件中定义我们的用户权限。关于CASL的一个很酷的事情是,它与环境无关的,这意味着它可以用在Node或任何浏览器中。

我们要使我们的权限定义在CommonJS的模块中以确保与Node的兼容性(注意WebPack可以变换模块中使用的客户端)。

resources/ability.js

const casl = require('casl');

module.exports = function defineAbilitiesFor(user) {

return casl.AbilityBuilder.define(

{ subjectName: item => item.type },

can => {

can(['read', 'create'], 'Post');

can(['update', 'delete'], 'Post', { user: user });

}

);

};

复制代码

让我们把代码细分一点:

我们可以看到第一个函数调用的方法中有二个参数,我们通过这个调用就可以定义权限规则。这种方法的第一个参数是你需要的CRUD操作,第二个是Post。

注意,在第二个函数调用中,我们传递了第三个参数是一个对象。这用于检测实体的用户属性是否匹配我们提供的用户对象。如果我们没有这样做,任何帖子就都可以被任何用户更新或删除,而不仅仅是帖子的所有者。

resources/ability.js

...

casl.AbilityBuilder.define(

...

can => {

can(['read', 'create'], 'Post');

can(['update', 'delete'], 'Post', { user: user });

}

);

复制代码

当CASL检查确定一个实体的权限时,它需要知道实体的类型。通常的一种方法是通过函数的属性subjectname作为定义方法的一个参数来传递一个对象。这个函数将返回实体的类型。

我们将通过返回实体上的type属性来实现这一点。我们需要确保当我们在某一个时刻定义我们的Post对象时,这个属性是存在的。

resources/ability.js

...

casl.AbilityBuilder.define(

{ subjectName: item => item.type },

...

);
复制代码

最后,我们在一个函数中封装我们的定义,这个函数允许我们在检测权限时传递用户对象。这样当我们在主应用程序中使用它时,就更好理解了,如下所示。

resources/ability.js

const casl = require('casl');

module.exports = function defineAbilitiesFor(user) {

...

};
复制代码

在Vue中使用访问权限规则

我们现在希望能够检测一个对象在我们的前端应用程序看到的CRUD操作允许用户执行它。我们需要我们的Vue组件内提供的使用规则。以下是如何实现:

import Vue和abilities plugin。这个插件添加CASL的Vue的原型,让我们从内部组件可以调用它。

Import 我们的规则集到Vue(如resources/abilities.js)

定义一个当前用户。在一个真正的应用程序中,我们可以从服务器获取这个用户数据。对于我们的示例,我们只需硬编码一个即可。

记住,abilities 模块的exports一个函数,我们称之为defineAbilitiesFor。我们要将用户对象传递给这个函数。现在,每当检测对象时,我们都可以看到当前用户可用的权限。

添加abilities插件,允许我们在组件内进行测试如 likethis.$can(...)。

src/main.js

import Vue from 'vue';

import abilitiesPlugin from './ability-plugin';

const defineAbilitiesFor = require('../resources/ability');

let user = { id: 1, name: 'George' };

let ability = defineAbilitiesFor(user.id);

Vue.use(abilitiesPlugin, ability);
复制代码

Post实体

我们的应用程序将使用表示分类广告职位的对象。他们可能是从数据库中检索,然后传递到前端的服务器,例如:

我们的Post实体必须有两个属性:

类型属性。CASL将使用定义在abilities.js的实体,通过subjectname回调来确定正在检测什么样的用户。

用户属性。这是Post的所有者。记住,用户只有拥有了更新和删除权限。在main.js我们已经告诉CASL他目前的用户是defineabilitiesfor(用户ID)。CASL现在所需要做的是检查用户的ID与用户属性。

let posts = [

{

type: 'Post',

user: 1,

content: '1 used cat, good condition'

},

{

type: 'Post',

user: 2,

content: 'Second-hand bathroom wallpaper'

}

];
复制代码

鉴于这两个Post对象,我们当前的用户乔治拥有ID 1,它将在第一个帖子上有更新/删除权限,但第二个帖子没有这个权限。

检测用户权限

在我们的应用程序中通过一个名为“帖子”的组件显示帖子。先看一下代码,然后我们把它分解到下面:

src/components/Post.vue

<template>

<div>

<div>

<br/><small>posted by </small>

</div>

<button @click="del">Delete</button>

</div>

</template>

<script>

import axios from 'axios';

export default {

props: ['post', 'username'],

methods: {

del() {

if (this.$can('delete', this.post)) {

...

} else {

this.$emit('err', 'Only the owner of a post can delete it!');

}

}

}

}

</script>

<style>...</style>
复制代码

当用户点击删除按钮的时候,删除方法是捕获一个被称为delete的处理程序。

然后,我们使用CASL检查,用户是否有权限操作this.$can('delete', post)。如果他们有这个权限,我们可以采取相应一些操作。如果没有一个则提示一个错误的消息,“只有这个职位的发布者可以删除它!”。

服务器端检测

在实际应用中,用户在前端deletes后,我们将删除的功能使用Ajax发送一个指令到一个API(应用程序接口),例如:

src/components/Post.vue

if (this.$can('delete', post)) {

axios.get(`/delete/${post.id}`, ).then(res => {

...

});

}
复制代码

我们会把CASL检测的逻辑放在服务器上,因为服务器来确认来自客户端的CRUD操作:

server.js

app.get("/delete/:id", (req, res) => {

let postId = parseInt(req.params.id);

let post = posts.find(post => post.id === postId);

if (ability.can('delete', post)) {

posts = posts.filter(cur => cur !== post);

res.json({ success: true });

} else {

res.json({ success: false });

}

});
复制代码

由于CASL是同构的,服务器上的对象可以从abilities.js中importability,我们不需要做任何重复的编码!

总结

这样,我们就有一个很好的方式,可以在一个Vue应用中很简单的管理用户权限了。

我相信this.$can('delete', post)比下面的代码好的多:

if (user.id === post.user && post.type === 'Post') {

...

}
复制代码

这不仅是更难阅读,而且,这里有一个隐含的规则,即用户可以删除一个帖子。毫无疑问,这条规则将在我们应用程序的其他地方使用,并且应该真正被抽象出来。这正是CASL可以为我们做。

感谢Sergii Stotskyi,CASL的创造者,支持这篇文章。

分享一个 Vue.js 2 的入门级全家桶系列教程:

1.vue.js 2 入门与提高: xc.hubwiz.com/course/vue.…

2.vuex 2 入门与提高: xc.hubwiz.com/course/vuex

3.vue-router 2 入门与提高: xc.hubwiz.com/course/vuer…

4.vue.js 2 工程化实践: xc.hubwiz.com/course/vueg…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值