B端产品的权限设计和实现

461 阅读4分钟

B端产品一般会涉及到多用户、多角色的访问、使用,因此需要权限控制用户对产品的使用。

我将产品权限分为以下几类,然后分别介绍设计思路。

  • 产品登录权限
  • 页面查看权限
  • 功能使用权限
  • 数据CRUD权限

01.产品登录权限

主要有账号密码登录、手机验证码登录、第三方登录(微信、QQ)等。

账号密码登录,需要在用户注册阶段或者管理员添加用户时,存储用户的用户名和密码,密码一般会进行加密存储,在用户登录时,将密码加密后与数据库中的密码进行比对,校验通过就放行。

new Promise(function (resolve, reject) {
// 查询用户是否存在
    let query_object = {$and: [{mobile_phone: username}, {company_id: company_id.toString()}]};
    User.find(query_object, function (err, users) {
        if (err) return console.error(err);
        if (users.length === 0 || users[0].status === '禁用') return response.send({
            status: 'error'
        });
        password_digest = users[0].password;
        user_id = users[0]._id;
        company_id = users[0].company_id;
        resolve(password_digest, user_id, company_id);
    });
}).then(() => {
// 比对密码是否相同
    if (bcrypt.compareSync(password, password_digest)) {
        const token = jwt.sign({
            username: username,
            user_id: user_id,
            company_id: company_id,
            refreshTime: NewDate.gettime(240)
        }, config.jwtSecret, {algorithm: 'HS256'});
        const last_login_time = NewDate.gettime(0);
        const user_json = {last_login_time: last_login_time};
        User.updateOne({_id: user_id}, user_json, function (err, result_user) {
            if (err) throw err;
            console.log('update user last login time success!');
        });
        return response.json({
            status: 'ok',
            token: token
        })
    }

手机验证码登录,需要在校验用户手机号无误后,后台生成验证码,然后调用第三方短信接口发送验证码,在用户提交登录请求后,校验用户提交的验证码和后台生成的验证码是否相同。

let smsCode = Math.random().toString().slice(-6);
let SmsCodeJson = JSON.stringify(smsCode);
let params = {
    "RegionId": RegionId,
    "SignName": SignName,
    "TemplateCode": TemplateCode,
    "PhoneNumbers": PhoneNumbers,
    "TemplateParam": `{"code":${SmsCodeJson}}`
};
client.request('SendSms', params, requestOption).then(
    (smsRes) => { onSendSuccess(res, smsRes) },
    (err) => { onSendFail(res, err) }
)
    .then(res => {
        // 验证码校验后是否报错
        captcha_check = checkDetail(res, captcha, response);
        return captcha_check;
    })
    .then((captcha_check) => {
        new Promise(function (resolve, reject) {
        // 查询用户
            let query_object = {$and: [{mobile_phone: mobile}, {company_id: company_id.toString()}]};
            User.find(query_object, function (err, user_result) {
                if (err) console.log(err);
                if (user_result.length === 1 & user_result[0].status === '正常') {
                    user_id = user_result[0]._id;
                    company_id = user_result[0].company_id;
                    resolve(user_id, company_id);
                } else {
                    throw 'error';
                }
                resolve(captcha_check);
            });
        }).then(() => {
        // 验证通过,放行
            return response.json({
                status: 'ok',
                token: token
            })
        })

第三方登录,以微信登录为例,可以看下官方时序图:

D0wkkHSbtC6VUSHX4WsjP5ssg5mdnEmXO8NGVGF34dxS9N1WCcq6wvquR4K_Hcut.png

02.页面查看权限 我们可以将页面类比为电影,你想到电影院看这场电影,你就要提供电影票。在产品权限的场景下,页面就是电影即资源,访问权限就是电影票。所以问题就变成了,每个页面对应一种访问权限。比如我有A权限,我可以查看1、2、3页面;我有B权限,我可以查看4、5、6页面。

实现思路上,权限对应到角色,角色对应到用户,根据用户分配的角色来判断用户有哪些权限。

下图是角色的配置页面原型图:

640.png

下图是添加用户时,配置用户的角色信息:

640 (1).png

在前端页面的设计中,就需要将每一个页面绑定一个权限,然后在用户访问时,根据用户所有的权限来和页面的权限进行比对,符合代表有权限即可以查看该页面。 该示例是umijs的实现方式,详细了解请访问 umijs.org/zh-CN/plugi…

有 src/access.ts 时启用。
​
介绍
我们约定了 src/access.ts 为我们的权限定义文件,该文件需要默认导出一个方法,导出的方法会在项目初始化时被执行。该方法需要返回一个对象,对象的每一个值就对应定义了一条权限。如下所示:
​
// src/access.ts
export default function(initialState) {
  const { userId, role } = initialState;
​
  return {
    canReadFoo: true,
    canUpdateFoo: role === 'admin',
    canDeleteFoo: foo => {
      return foo.ownerId === userId;
    },
  };
}
​
其中 initialState 是通过初始化状态插件 @umijs/plugin-initial-state 提供的数据,你可以使用该数据来初始化你的用户权限。

03.功能使用权限

功能主要以按钮的形式来展现,所以这里有两种处理方式: 在访问页面时,即根据用户的权限集判断用户是否有使用该功能的权限,如果没有则不显示该按钮;

访问页面时,默认展示所有按钮,在用户点击按钮时,校验该用户是否有该功能的使用权限。

04.数据CRUD权限 CRUD即数据的增删改查,这里面增、删、改都是动作,其实和功能使用权限类似,因此不展开,我们重点说一下查的部分。

如果我们需要实现只有数据的创建可以查看该数据,则需要在请求后端数据时,查询创建者为当前登录用户的数据然后再返回给前端。

这种权限还算简单,但扩展性比较差。

根据企业的组织架构,我们发现,数据权限可以有以下分类:

  • 个人:指定人员可以访问
  • 职位/角色:指定角色可以访问
  • 组织:指定组织可以访问

然后设计页面配置表,可以设置页面权限类型:

640 (2).png

其中【级联访问】的作用是,对于角色和组织来说一般会有上下级,如果允许级联访问,则有访问权限的角色或组织的上级都自动获得该权限。

然后在相应页面的数据创建时,我们就需要将用户的id、角色、组织等信息填入记录中,在我们请求后端数据时,根据该页面的权限类型,结合当前用户的id、角色、组织来返回符合权限要求的数据。

其他类型的数据权限实现方式类似,核心就是数据的权限和用户的权限能匹配上。

以上就是我对B端产品权限的理解,希望能对你有帮助。

欢迎大家关注我的公众号”凌云青年旅馆“