后臺(tái)管理權(quán)限

前端權(quán)限:因?yàn)榍岸吮緛?lái)就是不安全的,真正的安全還是需要后端去把關(guān),所以后端也必須按做權(quán)限控制!我們前端的權(quán)限校驗(yàn)主要的目的是過(guò)濾不該有的請(qǐng)求和操作线梗,減少服務(wù)端壓力
一般來(lái)說(shuō)前端權(quán)限在三個(gè)方面:接口權(quán)限、按鈕權(quán)限怠益,路由權(quán)限(菜單權(quán)限)

菜單權(quán)限實(shí)現(xiàn)步驟:

1.拆分動(dòng)態(tài)路由和靜態(tài)路由

原因:由于不同用戶登錄以后應(yīng)該有不同的權(quán)限仪搔,可以看到不同的內(nèi)容,因此需要給不同的用戶在菜單上分配不同的權(quán)限溉痢。
菜單權(quán)限最重要的一點(diǎn)就是:當(dāng)獲取用戶信息的時(shí)候僻造,服務(wù)器會(huì)把響應(yīng)的用戶擁有菜單的權(quán)限信息返回,需要根據(jù)用戶身份對(duì)比出孩饼,當(dāng)前這個(gè)用戶需要展示哪些菜單髓削。
靜態(tài)路由:不管用戶是什么角色,都可以看到的路由镀娶,比如登錄立膛、首頁(yè)、404;
動(dòng)態(tài)路由:不同的用戶需要過(guò)濾選出的路由宝泵;

//靜態(tài)路由
import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

import Layout from '@/layout'
// 靜態(tài)路由:不管是什么角色都可以看見(jiàn):登錄頁(yè)面好啰,404,首頁(yè)
export const constantRoutes = [
  {
    path: '/login',
    component: () => import('@/views/login/index'),
    hidden: true
  },
  {
    path: '/404',
    component: () => import('@/views/404'),
    hidden: true
  },
  {
    path: '/',
    component: Layout,
    // 重定向
    redirect: '/dashboard',
    children: [
      {
        path: 'dashboard',
        name: 'Dashboard',
        component: () => import('@/views/dashboard/index'),
        meta: { title: '首頁(yè)', icon: 'dashboard' }
      }
    ]
  },

  // 404 page must be placed at the end !!!
  { path: '*', redirect: '/404', hidden: true }
]
// 動(dòng)態(tài)路由:不同角色需要過(guò)濾篩選出的路由
export const asyncRoutes = [
  // 權(quán)限路由
  {
    name: 'Acl',
    path: '/acl',
    component: Layout,
    redirect: '/acl/user/list',
    meta: {
      title: '權(quán)限管理',
      icon: 'el-icon-lock'
    },
    children: [
      {
        name: 'User',
        path: 'user/list',
        component: () => import('@/views/acl/user/list'),
        meta: {
          title: '用戶管理'
        }
      }
    ]
  },
  {
    path: '/product',
    component: Layout,
    name: 'Product',
    // title:左側(cè)側(cè)邊欄名稱 icon小圖標(biāo)
    meta: { title: '商品管理', icon: 'el-icon-goods' },
    children: [
      {
        path: 'trademark',
        name: 'TradeMark',
        component: () => import('@/views/product/tradeMark'),
        meta: { title: '品牌管理' }
      },
     ]
    }儿奶,
  {
    path: '/test',
    component: Layout,
    name: 'Test',
    // title:左側(cè)側(cè)邊欄名稱 icon小圖標(biāo)
    meta: { title: '測(cè)試管理', icon: 'el-icon-goods' },
    children: [
      {
        path: 'test1',
        name: 'test1',
        component: () => import('@/views/Test/Test1'),
        meta: { title: '測(cè)試管理1' }
      },

2.分析登錄業(yè)務(wù)中的內(nèi)容

<el-button  type="primary" @click.native.prevent="handleLogin">登錄</el-button>

// 登錄業(yè)務(wù):發(fā)請(qǐng)求框往,帶著用戶名和密碼給服務(wù)器(成功與失敗)
    handleLogin() {
      // 驗(yàn)證表單元素(用戶名與密碼)的是否符合規(guī)則
      this.$refs.loginForm.validate(async valid => {
        // 如果符合驗(yàn)證規(guī)則
        if (valid) {
          // 按鈕會(huì)有一個(gè)loading效果
          this.loading = true
          // 派發(fā)一個(gè)action:user/login闯捎,帶著用戶名和密碼的載荷
          await this.$store.dispatch('user/login', this.loginForm)
          // 登陸成功進(jìn)行路由跳轉(zhuǎn)
          this.$router.push({ path: this.redirect || '/' })
          // loading效果結(jié)束
          this.loading = false
        } else {
          console.log('error submit!!')
          return false
        }
      })
    }

用戶信息模塊椰弊,主要功能:
1、登錄獲取token瓤鼻,存儲(chǔ)到Cookies中
2秉版、獲取用戶信息,存儲(chǔ)到Vuex中

import { login, logout, getInfo } from '@/api/user'
// 獲取token|設(shè)置token|刪除token的函數(shù)
import { getToken, setToken, removeToken } from '@/utils/auth'
// 引入路由中重置路由的方法
import { resetRouter, asyncRoutes, constantRoutes, anyRoutes } from '@/router'
import router from '@/router'
import cloneDeep from 'lodash/cloneDeep'

const getDefaultState = () => {
  return {
    // 獲取token
    token: getToken(),
    // 存儲(chǔ)用戶名
    name: '',
    // 存儲(chǔ)用戶頭像
    avatar: '',
    // 存儲(chǔ)菜單標(biāo)記(根據(jù)不同的角色茬祷,返回的標(biāo)記信息清焕,數(shù)組里面的元素是字符串)
    routes: [],
    // 存儲(chǔ)角色
    roles: [],
    // 按鈕權(quán)限
    buttons: [],
    // 項(xiàng)目中已有的異步路由和服務(wù)器返回的標(biāo)記信息對(duì)比之后,最終需要展示的路由
    resultAsyncRoutes: [],
    // 用戶最終需要展示的全部路由
    resultAllRoutes: []
  }
}
const state = getDefaultState()
const mutations = {
// 存儲(chǔ)token
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  // 存儲(chǔ)用戶信息
  SET_USERINFO: (state, userInfo) => {
    // 用戶名
    state.name = userInfo.name
    // 用戶頭像
    state.avatar = userInfo.avatar
    // 菜單權(quán)限的標(biāo)記
    state.routes = userInfo.routes
    // 按鈕權(quán)限的標(biāo)記
    state.button = userInfo.button
    // 角色
    state.roles = userInfo.roles
  },
}
const actions = {
  // user login
  // 處理登陸的業(yè)務(wù)
  async login({ commit }, userInfo) {
    // 解構(gòu)出用戶名和密碼
    const { username, password } = userInfo
    const result = await login({ username: username.trim(), password: password })
    // 注意:當(dāng)前登陸的請(qǐng)求 使用的是mock數(shù)據(jù)祭犯,mock數(shù)據(jù)code是20000
    if (result.code === 20000) {
      // vuex存儲(chǔ)token秸妥,修改state必須通過(guò)mutations
      commit('SET_TOKEN', result.data.token)
      // 本地持久化存儲(chǔ)token
      setToken(result.data.token)
      return 'ok'
    } else {
      return Promise.reject(new Error('faile'))
    }
},
// 獲取用戶信息
getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo(state.token).then((response) => {
        // 獲取用戶信息:返回?cái)?shù)據(jù)包括用戶名,用戶頭像盹憎,routes(返回的標(biāo)志:不同的用戶應(yīng)該展示哪些菜單的標(biāo)記)
        // (roles:用戶角色信息)(button:按鈕信息筛峭,按鈕權(quán)限使用的標(biāo)記)

        const { data } = response
        // vuex存儲(chǔ)用戶的全部信息
        commit('SET_USERINFO', data)
        // 提交數(shù)據(jù)
        commit('SET_RESULTASYNCROUTES', computedAsyncRoutes(cloneDeep(asyncRoutes), data.routes))
        resolve(data)
      })
        .catch((error) => {
          reject(error)
        })
    })
  }

下載cookie插件

import Cookies from 'js-cookie'

const TokenKey = 'vue_admin_template_token' // 設(shè)置一個(gè)獨(dú)一無(wú)二的key

export function getToken() {
  return Cookies.get(TokenKey) //get獲取token
}

export function setToken(token) {
  return Cookies.set(TokenKey, token) // set設(shè)置token
}

export function removeToken() {
  return Cookies.remove(TokenKey) //remove移除token
}

3.在全局路由前置守衛(wèi)中判斷是否有token铐刘,要訪問(wèn)的是否是登錄頁(yè)面陪每,是否有用戶信息

// 全局前置守衛(wèi)
router.beforeEach(async(to, from, next) => {
  //  開(kāi)啟進(jìn)度條
  NProgress.start()

  document.title = getPageTitle(to.meta.title)

  const hasToken = getToken()
  // 如果有token
  if (hasToken) {
    // 如果要訪問(wèn)的是登錄頁(yè)面
    if (to.path === '/login') {
      // 跳到主頁(yè),有token不用處理
      next({ path: '/' })
      NProgress.done()
    } else {
      const hasGetUserInfo = store.getters.name
      // 如果有用戶信息
      if (hasGetUserInfo) {
        next()
      } else {
        try {
          // 獲取用戶信息
          await store.dispatch('user/getInfo')

          next()
        } catch (error) {
          // 移除token
          await store.dispatch('user/resetToken')
          Message.error(error || 'Has Error')
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
  } else {
    // 沒(méi)有token

    if (whiteList.indexOf(to.path) !== -1) {
      // 在白名單登錄頁(yè)面中镰吵,直接進(jìn)入
      next()
    } else {
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }
})

4.對(duì)比異步路由檩禾,相同則展示對(duì)應(yīng)路由

// 定義一個(gè)函數(shù):兩個(gè)數(shù)組進(jìn)行對(duì)比,對(duì)比出當(dāng)前用戶顯示哪些異步路由
const computedAsyncRoutes = (asyncRoutes, routes) => {
  // 過(guò)濾出當(dāng)前用戶(超級(jí)管理員疤祭,普通員工)需要展示的異步路由
  return asyncRoutes.filter(item => {
    // 數(shù)組中沒(méi)有這個(gè)元素返回索引值-1盼产,如果有,返回的索引值一定不是-1
    if (routes.indexOf(item.name) !== -1) {
      // 遞歸:還有2,3,4勺馆,級(jí)多級(jí)路由的情況
      if (item.children && item.children.length) {
        item.children = computedAsyncRoutes(item.children, routes)
      }
      return true
    }
  })
}

5.菜單權(quán)限設(shè)置成功

const mutations = {
  // 最終計(jì)算出來(lái)的異步路由
  SET_RESULTASYNCROUTES: (state, asyncRoutes) => {
    // vuex保存當(dāng)前用戶的異步路由戏售,用戶需要展示的完整路由包括常量,異步草穆,任意路由
    state.resultAsyncRoutes = asyncRoutes
    // 計(jì)算出當(dāng)前用戶需要展示的所有路由,合并
    state.resultAllRoutes = constantRoutes.concat(state.resultAsyncRoutes, anyRoutes)
    // 給路由器添加新的路由
    router.addRoutes(state.resultAllRoutes)
  }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灌灾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子悲柱,更是在濱河造成了極大的恐慌锋喜,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異嘿般,居然都是意外死亡段标,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)炉奴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)逼庞,“玉大人,你說(shuō)我怎么就攤上這事瞻赶⊥ぃ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵共耍,是天一觀的道長(zhǎng)虑灰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)痹兜,這世上最難降的妖魔是什么穆咐? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮字旭,結(jié)果婚禮上对湃,老公的妹妹穿的比我還像新娘。我一直安慰自己遗淳,他們只是感情好拍柒,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著屈暗,像睡著了一般拆讯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上养叛,一...
    開(kāi)封第一講書(shū)人閱讀 52,696評(píng)論 1 312
  • 那天种呐,我揣著相機(jī)與錄音,去河邊找鬼弃甥。 笑死爽室,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的淆攻。 我是一名探鬼主播阔墩,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瓶珊!你這毒婦竟也來(lái)了啸箫?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤艰毒,失蹤者是張志新(化名)和其女友劉穎筐高,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柑土,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年蜀肘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稽屏。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡扮宠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出狐榔,到底是詐尸還是另有隱情坛增,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布薄腻,位于F島的核電站收捣,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏庵楷。R本人自食惡果不足惜罢艾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望尽纽。 院中可真熱鬧咐蚯,春花似錦、人聲如沸弄贿。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)差凹。三九已至期奔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間直奋,已是汗流浹背能庆。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留脚线,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓弥搞,卻偏偏與公主長(zhǎng)得像邮绿,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子攀例,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容