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
})
})
第三方登录,以微信登录为例,可以看下官方时序图:
02.页面查看权限 我们可以将页面类比为电影,你想到电影院看这场电影,你就要提供电影票。在产品权限的场景下,页面就是电影即资源,访问权限就是电影票。所以问题就变成了,每个页面对应一种访问权限。比如我有A权限,我可以查看1、2、3页面;我有B权限,我可以查看4、5、6页面。
实现思路上,权限对应到角色,角色对应到用户,根据用户分配的角色来判断用户有哪些权限。
下图是角色的配置页面原型图:
下图是添加用户时,配置用户的角色信息:
在前端页面的设计中,就需要将每一个页面绑定一个权限,然后在用户访问时,根据用户所有的权限来和页面的权限进行比对,符合代表有权限即可以查看该页面。 该示例是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即数据的增删改查,这里面增、删、改都是动作,其实和功能使用权限类似,因此不展开,我们重点说一下查的部分。
如果我们需要实现只有数据的创建可以查看该数据,则需要在请求后端数据时,查询创建者为当前登录用户的数据然后再返回给前端。
这种权限还算简单,但扩展性比较差。
根据企业的组织架构,我们发现,数据权限可以有以下分类:
- 个人:指定人员可以访问
- 职位/角色:指定角色可以访问
- 组织:指定组织可以访问
然后设计页面配置表,可以设置页面权限类型:
其中【级联访问】的作用是,对于角色和组织来说一般会有上下级,如果允许级联访问,则有访问权限的角色或组织的上级都自动获得该权限。
然后在相应页面的数据创建时,我们就需要将用户的id、角色、组织等信息填入记录中,在我们请求后端数据时,根据该页面的权限类型,结合当前用户的id、角色、组织来返回符合权限要求的数据。
其他类型的数据权限实现方式类似,核心就是数据的权限和用户的权限能匹配上。
以上就是我对B端产品权限的理解,希望能对你有帮助。
欢迎大家关注我的公众号”凌云青年旅馆“