后臺(tái)管理系統(tǒng)element-admin——登錄權(quán)限篇

Start

記錄寫(xiě)后臺(tái)管理系統(tǒng)時(shí)的一些想法和組件的二次封裝,項(xiàng)目初期參考的是花褲衩大神的vue-element-admin,后期根據(jù)業(yè)務(wù)進(jìn)行了一些修改。

登錄

登錄流程的思路我們先屢清楚:

  • 用戶在登錄頁(yè)輸入賬號(hào)密碼,將賬號(hào)密碼發(fā)送請(qǐng)求給后端
    • 將賬號(hào)密碼發(fā)送請(qǐng)求給后端的方法寫(xiě)在vuex里便于全局token的存取,而前端登錄方法里只需要關(guān)注登錄的結(jié)果,并根據(jù)結(jié)果跳轉(zhuǎn)頁(yè)面或提示錯(cuò)誤,這樣代碼結(jié)構(gòu)會(huì)清晰。
    <!-- action: -->
    
    Login ({commit}, userInfo) {
      const { username, password } = userInfo
      return new Promise((resolve, reject) => {
        login({ username: username.trim(), password: password })
          .then(res => {
            if (res.event !== 0) {
              reject(res)
            }
            Vue.ls.set(ACCESS_TOKEN, res.data.token, 12 * 60 * 60 * 1000)
            commit('SET_TOKEN', res.data.token)
            resolve()
          })
          .catch ((error) => {
            reject(error)
          })
      })
    }
    
    <!-- Login頁(yè)面: -->
    
    import { mapActions } from 'vuex'
    
    methods: {
    ...mapActions(['Login']),
    handleLogin () {
      this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true
          this.Login(this.loginForm)
            .then(() => {
              this.$router.push({ path: this.redirect || '/' }).catch(err => {})
              this.loading = false
            }).catch((err) => {
              this.$message.error(err.message);
              this.loading = false
            })
        } else {
          console.log('error submit!!')
          return false
        }
      })
    }
    }
    
  • 后端驗(yàn)證一下用戶的賬號(hào)和密碼的信息,如果符合就發(fā)一個(gè)token返回給客戶端,如果不符合就不發(fā)送token,返回驗(yàn)證錯(cuò)誤信息。
  • 如果登錄成功,客戶端將token存在localStorage里,之后要請(qǐng)求其他資源的時(shí)候,在請(qǐng)求頭里帶上這個(gè)token。
    • service/http.js 中全局請(qǐng)求攔截器中:config.headers['token'] = token。
  • 后端收到請(qǐng)求信息,先驗(yàn)證下token是否有效,有效則下發(fā)請(qǐng)求的資源,無(wú)效則返回驗(yàn)證錯(cuò)誤。

獲取用戶信息

登錄成功之后,在全局路由鉤子router.beforeEach中攔截路由,判斷如果有token,就去獲取用戶信息

<!-- router.beforeEach -->

if (Vue.ls.get(ACCESS_TOKEN)) {
  store.dispatch('GetInfo')
  .then((infoRes) => {
    const roles = res.data.role;
    next()
  })
}

權(quán)限

權(quán)限控制是很常見(jiàn)的需求,我們的業(yè)務(wù)要求控制到按鈕級(jí)別。

頁(yè)面級(jí)權(quán)限的實(shí)現(xiàn)方式是通過(guò)獲取當(dāng)前用戶的權(quán)限去對(duì)比路由表,生成當(dāng)前用戶具有權(quán)限可訪問(wèn)的路由表,通過(guò) router.addRouters 掛載到 router 上。

具體步驟如下:

  1. 判斷是否有token,如果沒(méi)有就去登錄,有就第二步。
  2. 獲取用戶信息 store.dispatch('GetInfo')
  3. 獲取信息成功之后,調(diào)用store.dispatch('GenerateRoutes'),這個(gè)方法里會(huì)調(diào)用/router/index.js里的 generatorDynamicRouter 方法,并返回一個(gè)根據(jù)用戶信息構(gòu)建好權(quán)限的路由結(jié)構(gòu)。(generatorDynamicRouter方法里將后臺(tái)返回的一個(gè)平級(jí)的menu信息,通過(guò)遞歸的方式生成層級(jí)結(jié)構(gòu),再遞歸生成層級(jí)路由)
  4. 將構(gòu)建的路由結(jié)構(gòu)信息利用 Vue-Router 提供的動(dòng)態(tài)增加路由方法 router.addRoutes 加入到路由表中。
  5. 加入路由表后將頁(yè)面跳轉(zhuǎn)到用戶原始要訪問(wèn)的頁(yè)面,如果沒(méi)有 redirect 則進(jìn)入默認(rèn)頁(yè)面。

我們把 登錄獲取用戶信息 分成了兩個(gè)接口,原因是當(dāng)用戶刷新頁(yè)面時(shí),可以根據(jù)登錄時(shí)獲取到的token去獲取用戶信息,避免了刷新還要調(diào)用登錄接口。

整體流程可以看這個(gè)圖:


promission

前端控制權(quán)限

舊版本后臺(tái)的路由表是后端同學(xué)根據(jù)權(quán)限生成的,這使得前端小伙伴每開(kāi)發(fā)一個(gè)頁(yè)面就需要讓后端同學(xué)配一下路由和權(quán)限,光聽(tīng)著就開(kāi)始皺眉了???♀?。

于是我們采用了在前端頁(yè)面配置路由和權(quán)限,之后將這份路由表存到后端。

權(quán)限/菜單:


image

權(quán)限/角色:


image

一角色對(duì)應(yīng)多權(quán)限,一用戶對(duì)應(yīng)多角色

當(dāng)用戶登錄后得到 roles,前端根據(jù) roles 去向后端請(qǐng)求可訪問(wèn)的路由表,從而動(dòng)態(tài)生成可訪問(wèn)頁(yè)面,之后就是 router.addRoutes 動(dòng)態(tài)掛載到 router 上,和原來(lái)是相同的。

按鈕級(jí)權(quán)限

在配置菜單權(quán)限頁(yè)面也可以添加配置按鈕的權(quán)限,登錄之后的 store.dispatch('GetInfo') 中能拿到對(duì)應(yīng)權(quán)限的按鈕,并存儲(chǔ)在 vuex 中。

判斷按鈕是否展示是寫(xiě)了一個(gè)公用方法 checkPermission ,沒(méi)有用指令是因?yàn)闊o(wú)法適用于所有組件。

將提前設(shè)置好的 唯一鍵 傳入方法,就可以從vuex里 store.getters.buttons 拿到所有按鈕權(quán)限,對(duì)比后返回 true 或 false,來(lái)控制按鈕的展示。

<!-- 引入方法 -->
import { checkPermission } from '@/utils/permissions'

<!-- data中定義變量 -->
addEnable: checkPermission('system:role:add')

<!-- v-if判斷 -->
<el-button v-if="addEnable">添加角色</el-button>

最后

代碼地址戳這里哈~
附圖:

image

image

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

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

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