相关文章
基于阿里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.*']
}
}
结尾
如果看完觉得有用,请给作者一个喜欢吧!谢谢啦!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。