JavaScript 权限算法运用

159 阅读2分钟

开发经常碰到项目复杂的权限控制,有过后台开发经验的人都知道RBAC权限数据设计,但现在的软件开发,RBAC只能单纯的控制模块功能,但不能控制更加细化的Action,而且很多设计者会在权限拦截器中做Sql查询该请求的权限控制,但这种方式效率极差,而且在企业大型的平台中更加的不适用,但也有设计者在程序单点登陆的时候将权限以字符串的形式用Cookie的形式保存Response中,虽然绕过了DB层的操作,但是发出去一个没有权限且无用的请求,这在一个高效的Web程序中,也是不可以接受的,同时,这种方式复用率很低,权限算法正好是解决这种问题的实践运用,不废话,直接上干货。

class Right {
   //get 是一个封装好的属性,它保存着我们数据库的对应的权限键值和对应的索引。
    get authRight() {

        //假如这里是我们的App权限应用列表,对应数据库中的权限索引。
        return {
            'read' : 0,
            'write' : 1,
            'read_write' : 2,
            'view' : 3,
            'root' : 4,
            'anonymous' : 5
        }
    }
    //calcRight 是对当前用户的权限进行加密,这里面使用2 ^ index 幂, 注意:^ 不是异或
    calcRight(rights = []) {

        let rightList = this.authRight;
        let rigth = 0;
        for(let [i, v] of rights.entries()) {
            if(v in rightList) {
                rigth += Math.pow(2, rightList[v]);
            }
        }
        return rigth;
    }
    //这里是判断当前用户的权限列表是否包含某一个权限能力。
    checkRight(right = 0, operation = '') {
        if(right === void 0) {
            return false;
        }
        if(operation in this.authRight) {
            let rightBit = this.authRight[operation];
            let newRight = right.toString(2);
            return newRight.charAt(newRight.length - rightBit - 1) === '1';
        }
        return false;
    }
}

上面是一断ES6语法编写的权限算法类,在这里解释一下这个算法的运用。

假如我们现在在平台登陆的时候,后台使用Sql查询用户信息,则用户信息中包含权限信息:

select id, key from Right where userid = 1; // [[4, 'root'], [3, 'view'], [5, 'anonymous']]

后台则调用calcRight函数,将查询出来的结果返回给前端:

right.calcRight(['root','view', 'anonymous']);

// root === (2 ^ 4) = (2 * 2 * 2 * 2) = 16

// view === (2 ^ 3) = (2 * 2 * 2) = 8

// anonymous === (2 ^ 5) = (2 * 2 * 2 * 2 * 2) = 32

// root + view + anonymous === 56

前端拿到这个权限值 56之后,在所有的ajax 的beforeSend函数之前进行checkRight验证。

比如:

this.$ajax.get() //假如get请求只能做read权限

rigth.checkRight(56, 'read'); //false

rigth.checkRight(56, 'root'); //true

rigth.checkRight(56, 'view'); //true

rigth.checkRight(56, 'anonymous'); //true

在get请求中,我们可以验证到当前用户没有read权限,所以我们可以在beforeSend中直接断开请求。