相關文章
基於阿里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.*']
}
}
結尾
如果看完覺得有用,請給作者一個喜歡吧!謝謝啦!