基于阿里egg框架搭建博客(4)——權(quán)限控制

相關(guān)文章

基于阿里egg框架搭建博客(1)——開發(fā)準(zhǔn)備
基于阿里egg框架搭建博客(2)——Hello World
基于阿里egg框架搭建博客(3)——注冊與登錄
基于阿里egg框架搭建博客(4)——權(quán)限控制
基于阿里egg框架搭建博客(5)——置頂導(dǎo)航條
基于阿里egg框架搭建博客(6)——瀏覽、發(fā)表文章
基于阿里egg框架搭建博客(7)——編輯文章

git

https://github.com/ZzzSimon/egg-example
喜歡就點(diǎn)個(gè)贊吧!

正文

上一篇文章我們實(shí)現(xiàn)了用戶的注冊與登錄,接下來就需要對用戶權(quán)限進(jìn)行控制了,比如:普通用戶只能評(píng)論,管理員可以發(fā)表文章,最高管理員可以修改用戶權(quán)限等等。
由于權(quán)限控制是一個(gè)通用的功能,我們把這塊功能做成中間件。關(guān)于中間件:

官方文檔:https://eggjs.org/zh-cn/basics/middleware.html

功能設(shè)計(jì)

  1. 一個(gè)用戶對應(yīng)1個(gè)角色
  2. 可以通過配置文件配置,某一個(gè)角色無權(quán)限使用的頁面與接口
  3. 可以配置無需驗(yàn)證用戶與權(quán)限的path。比如:登錄與注冊的相關(guān)頁面與接口
  4. 只有登錄過才能訪問的path,否則跳轉(zhuǎn)登錄頁。

User表,增加role(角色)字段

配置文件

我們在config/config.default.js中加入以下內(nèi)容:

        auth : {
            noAuth:['/login.htm','/user/login','/register.htm','/user/register'],
            noPermission:{
                admin:[],
                manager:['/admin.htm'],
                user:['/admin.htm','/edit.htm']
            }
        }

其中:
noAuth節(jié)點(diǎn)配置的是無需驗(yàn)權(quán)就能訪問的path
noPermission節(jié)點(diǎn)配置的是各個(gè)角色無權(quán)限訪問的path

auth.js中間件代碼

我們創(chuàng)建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;
            //這里有兩種做法,第一種每次都查庫校驗(yàn)角色,優(yōu)點(diǎn):實(shí)時(shí),角色變更對用戶無感。缺點(diǎn):查庫效率低,可考慮用redis
            //第二種,把角色信息放進(jìn)session,優(yōu)點(diǎn):無需查庫,效率高。缺點(diǎn):角色變更時(shí)需額外邏輯來處理老的session,否則客戶端的用戶角色無法實(shí)時(shí)更新
            const role = await ctx.service.user.getRoleByUsername(username);
            const noPerList = options.noPermission[role];
            if (noPerList && !noPerList.includes(ctx.path)) {
                await next();
            } else {
                ctx.body = '無權(quán)限,請聯(lián)系網(wǎng)站管理員!';
            }
            //登錄注冊頁面不需要權(quán)限
        } else if (options.noAuth.includes(ctx.path)) {
            await next();
            //如果session失效后則重定向到登錄頁
        } else {
            ctx.redirect('/login.htm')
        }
    }
};

效果

我們創(chuàng)建一個(gè)用戶,并給與他user角色,由配置文件可以看出,user角色無權(quán)限訪問/edit.htm路徑。如圖:

正則匹配

如果頁面也來越多,或者有些帶參數(shù)的path是動(dòng)態(tài)的,我們需要一定的規(guī)則來過濾path。這時(shí)候就需要用到正則匹配,我們修改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;
            //這里有兩種做法,第一種每次都查庫校驗(yàn)角色,優(yōu)點(diǎn):實(shí)時(shí),角色變更對用戶無感。缺點(diǎn):查庫效率低,可考慮用redis
            //第二種,把角色信息放進(jìn)session,優(yōu)點(diǎn):無需查庫,效率高。缺點(diǎn):角色變更時(shí)需額外邏輯來處理老的session,否則客戶端的用戶角色無法實(shí)時(shí)更新
            const role = await ctx.service.user.getRoleByUsername(username);
            const noPerList = options.noPermission[role];
            if (noPerList && !isNoPer(noPerList,ctx.path)) {
                await next();
            } else {
                ctx.body = '無權(quán)限,請聯(lián)系網(wǎng)站管理員!';
            }
            //登錄注冊頁面不需要權(quán)限
        } else if (options.noAuth.includes(ctx.path)) {
            await next();
            //如果session失效后則重定向到登錄頁
        } else {
            ctx.redirect('/login.htm')
        }
    }
};

這時(shí)候我們的配置文件就可以支持正則表達(dá)式了:

        auth : {
            noAuth:['/login.htm','/user/login','/register.htm','/user/register'],
            noPermission:{
                admin:[],
                manager:['/admin.htm'],
                user:['/admin.htm','/edit.*']
            }
        }

結(jié)尾

如果看完覺得有用,請給作者一個(gè)喜歡吧!謝謝啦!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容