相关文章
基于阿里 egg 框架搭建博客(1)——开发准备
基于阿里 egg 框架搭建博客(2)——Hello World
基于阿里 egg 框架搭建博客(3)——注册与登录
基于阿里 egg 框架搭建博客(4)——权限控制
基于阿里 egg 框架搭建博客(5)——置顶导航条
基于阿里 egg 框架搭建博客(6)——浏览、发表文章
基于阿里 egg 框架搭建博客(7)——编辑文章
git
https://github.com/ZzzSimon/e…
喜欢就点个赞吧!
正文
上一篇文章我们实现了用户的注册与登录,接下来就需要对用户权限进行控制了,比如:普通用户只能评论,管理员可以发表文章,最高管理员可以修改用户权限等等。
由于权限控制是一个通用的功能,我们把这块功能做成中间件。关于中间件:
官方文档:https://eggjs.org/zh-cn/basic…
功能设计
- 一个用户对应 1 个 角色
- 可以通过配置文件配置,某一个角色 无权限 使用的页面与接口
- 可以配置无需验证用户与权限的 path。比如:登录与注册的相关页面与接口
- 只有登录过才能访问的 path,否则跳转登录页。
User 表,增加 role(角色)字段
配置文件
我们在 config/config.default.js 中加入以下内容:
auth : {noAuth:['/login.htm','/user/login','/register.htm','/user/register'],
noPermission:{admin:[],
manager:['/admin.htm'],
user:['/admin.htm','/edit.htm']
}
}
其中:noAuth
节点配置的是无需验权就能访问的 pathnoPermission
节点配置的是各个角色 无权限 访问的 path
auth.js 中间件代码
我们创建 app/middleware/auth.js
文件:
module.exports = (options, app) => {return async function auth(ctx, next) {
// 如果用户 session 没失效
if (typeof (ctx.session.user) !== 'undefined') {
const username = ctx.session.user.username;
// 这里有两种做法,第一种每次都查库校验角色,优点:实时,角色变更对用户无感。缺点:查库效率低,可考虑用 redis
// 第二种,把角色信息放进 session, 优点:无需查库,效率高。缺点:角色变更时需额外逻辑来处理老的 session,否则客户端的用户角色无法实时更新
const role = await ctx.service.user.getRoleByUsername(username);
const noPerList = options.noPermission[role];
if (noPerList && !noPerList.includes(ctx.path)) {await next();
} else {ctx.body = '无权限,请联系网站管理员!';}
// 登录注册页面不需要权限
} else if (options.noAuth.includes(ctx.path)) {await next();
// 如果 session 失效后则重定向到登录页
} else {ctx.redirect('/login.htm')
}
}
};
效果
我们创建一个用户,并给与他 user 角色,由配置文件可以看出,user 角色无权限访问 /edit.htm
路径。如图:
正则匹配
如果页面也来越多,或者有些带参数的 path 是动态的,我们需要一定的规则来过滤 path。这时候就需要用到正则匹配,我们修改 auth.js
文件:
module.exports = (options, app) => {function isNoPer(noPerList,path) {for (let i = 0;i<noPerList.length;i++){const patt=new RegExp(noPerList[i]);
if (patt.test(path)) {return true;}
}
return false;
}
return async function auth(ctx, next) {
// 如果用户 session 没失效
if (typeof (ctx.session.user) !== 'undefined') {
const username = ctx.session.user.username;
// 这里有两种做法,第一种每次都查库校验角色,优点:实时,角色变更对用户无感。缺点:查库效率低,可考虑用 redis
// 第二种,把角色信息放进 session, 优点:无需查库,效率高。缺点:角色变更时需额外逻辑来处理老的 session,否则客户端的用户角色无法实时更新
const role = await ctx.service.user.getRoleByUsername(username);
const noPerList = options.noPermission[role];
if (noPerList && !isNoPer(noPerList,ctx.path)) {await next();
} else {ctx.body = '无权限,请联系网站管理员!';}
// 登录注册页面不需要权限
} else if (options.noAuth.includes(ctx.path)) {await next();
// 如果 session 失效后则重定向到登录页
} else {ctx.redirect('/login.htm')
}
}
};
这时候我们的配置文件就可以支持正则表达式了:
auth : {noAuth:['/login.htm','/user/login','/register.htm','/user/register'],
noPermission:{admin:[],
manager:['/admin.htm'],
user:['/admin.htm','/edit.*']
}
}
结尾
如果看完觉得有用,请给作者一个喜欢吧!谢谢啦!