Vue3 + TypeScript + Gin 實(shí)現(xiàn)后臺權(quán)限管理平臺

最近一直在學(xué)習(xí) Vue3 相關(guān)的技術(shù)棧,包括 CompositionAPI 、TypeScript、vite以及Element UI 對 Vue3 的支持版本 Element Plus。

因此想要使用 Vue3 寫一個(gè)簡單的 RBAC 的用戶權(quán)限系統(tǒng)。

之前一直是使用 MySQL 這個(gè)關(guān)系型數(shù)據(jù)庫,正好最近在學(xué)習(xí) Kong 網(wǎng)關(guān)的時(shí)候,接觸到了 Postgres 這個(gè)關(guān)系型數(shù)據(jù)庫,并且還看到了一句話,說是:“MySQL 是目前使用最廣泛的數(shù)據(jù)庫,但是 Postgres 是目前最先進(jìn)的數(shù)據(jù)庫?!?/p>

當(dāng)然這個(gè)最先進(jìn)也是 Postgres 的開源組織自己標(biāo)榜的。但是對我來說,Postgres 貌似確實(shí)要比 MySQL 用起來爽,最起碼在數(shù)據(jù)類型的支持方面,就是一個(gè)非常不錯(cuò)的點(diǎn)。

我經(jīng)常會使用 Json 或者 Array 這種字段,Postgres 就支持的非常不錯(cuò),當(dāng)然 MySQL 5.7 以后也是支持 Json 字段的,但是從性能和使用上來說,我還感覺還是 Postgres 用的更好一些,也不排除,是我自己對 MySQL 了解不深入。

好了,廢話不多說,我們來實(shí)際看看項(xiàng)目吧。

本項(xiàng)目不管是前后端都不會進(jìn)行過度的封裝,該封裝的封裝,不該封裝的就不會進(jìn)行封裝,不會為了裝 X 而過度封裝代碼,減少大家在看代碼的時(shí)間成本。

演示站點(diǎn):http://fdevops.com:8088

github:https://github.com/lanyulei/sky , 如果覺得還可以,還請不要吝嗇指尖的跳動,輕輕點(diǎn)上一個(gè) star 。

Casbin 權(quán)限控制

本系統(tǒng),使用 Casbin 作為接口的權(quán)限管理依賴,使用 RBAC 的方式進(jìn)行管理,支持用戶的多角色綁定。

Casbin 模型文件內(nèi)容如下:

[request_definition]
r = sub, obj, act
 
[policy_definition]
p = sub, obj, act
 
[role_definition]
g = _, _
 
[policy_effect]
e = some(where (p.eft == allow))
 
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

其實(shí)就是 Casbin 官網(wǎng)上給出的 RBAC 模型內(nèi)容,如果需要使用自定義函數(shù),可參考官網(wǎng)自行添加即可。

https://casbin.org/docs/zh-CN/function

Casbin Gin 中間件的簡單封裝。

package permission
 
import (
    "sky/pkg/conn"
    "sky/pkg/logger"
    "sky/pkg/tools/response"
    "time"
 
    "github.com/casbin/casbin/v2"
    gormAdapter "github.com/casbin/gorm-adapter/v3"
    "github.com/gin-gonic/gin"
    "github.com/spf13/viper"
)
 
var Enforcer *casbin.SyncedEnforcer
 
func CasbinSetup() *casbin.SyncedEnforcer {
    var (
        err     error
        adapter *gormAdapter.Adapter
    )
    adapter, err = gormAdapter.NewAdapterByDBWithCustomTable(conn.Orm, nil, viper.GetString("casbin.tableName"))
    if err != nil {
        logger.Fatal("創(chuàng)建 casbin gorm adapter 失敗,錯(cuò)誤:%v", err)
    }
 
    Enforcer, err = casbin.NewSyncedEnforcer(viper.GetString("casbin.rbacModel"), adapter)
    if err != nil {
        logger.Fatal("創(chuàng)建 casbin enforcer 失敗,錯(cuò)誤:%v", err)
    }
 
    err = Enforcer.LoadPolicy()
    if err != nil {
        logger.Fatal("從數(shù)據(jù)庫加載策略失敗,錯(cuò)誤:%v", err)
    }
 
    // 定時(shí)同步策略
    if viper.GetBool("casbin.isTiming") {
        // 間隔多長時(shí)間同步一次權(quán)限策略,單位:秒
        Enforcer.StartAutoLoadPolicy(time.Second * time.Duration(viper.GetInt("casbin.intervalTime")))
    }
 
    return Enforcer
}
 
func CheckPermMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        //獲取資源
        obj := c.Request.URL.Path
        //獲取方法
        act := c.Request.Method
        //獲取實(shí)體
        sub := c.GetString("username")
 
        isAdmin := c.GetBool("isAdmin")
        if isAdmin {
            c.Next()
        } else {
            //判斷策略中是否存在
            if ok, _ := Enforcer.Enforce(sub, obj, act); ok {
                c.Next()
            } else {
                response.Error(c, nil, response.NoPermissionError)
                c.Abort()
            }
        }
    }
}

菜單權(quán)限

菜單通過對角色可訪問的菜單標(biāo)識進(jìn)行權(quán)限控制,可使多個(gè)菜單標(biāo)識。

路由實(shí)例如下:

{
    path: '/user',
    name: 'User',
    component: () => import('/@/views/user/list.vue'),
    meta: {
        title: '用戶列表',
        auth: ['system:user:list'] // 此為路由標(biāo)識,只有角色關(guān)聯(lián)了此標(biāo)識,才可訪問。
    },
}

校驗(yàn)當(dāng)前用戶是否有權(quán)限,用戶的權(quán)限標(biāo)識列表將存入到 Vuex 中,當(dāng)前系統(tǒng)給用戶定義了超級管理員的概念,因此當(dāng)遇到程序是超級管理員的話,則直接放行。

export function setFilterRoute(chil: any) {
    let filterRoute: any = [];
    chil.forEach((route: any) => {
        if (route.meta.auth) {
            route.meta.auth.forEach((metaAuth: any) => {
                store.state.userInfos.userInfos.authPageList.forEach((auth: any) => {
                    // 如果是超級管理員,則直接通過
                    if (store.state.userInfos.userInfos.is_admin || metaAuth === auth) filterRoute.push({ ...route });
                });
            });
        }
    });
    return filterRoute;
}

項(xiàng)目演示

菜單管理,進(jìn)行菜單創(chuàng)建、頁面元素創(chuàng)建及菜單綁定 API 接口。

image.png

為菜單綁定 API 接口方便進(jìn)行接口權(quán)限管理。

image.png

頁面元素管理,包括但是不限于按鈕。

image.png

接口管理,后端所有需要通過 Casbin 進(jìn)行接口校驗(yàn)的接口。

image.png

為角色授權(quán)。

image.png

截圖內(nèi)容,僅是功能的一部分,詳細(xì)的內(nèi)容,可自行訪問演示站點(diǎn)查看。

有任何問題,可以到此處進(jìn)行留言討論,https://www.fdevops.com 。

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

相關(guān)閱讀更多精彩內(nèi)容

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