欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

前端權(quán)限控制和管理實(shí)現(xiàn)步驟詳解

 更新時(shí)間:2025年03月15日 09:34:26   作者:太陽(yáng)與星辰  
這篇文章主要介紹了前端權(quán)限控制的相關(guān)概念和實(shí)現(xiàn)思路,前端權(quán)限控制不僅可以提高安全性,還可以提升用戶體驗(yàn),文中將實(shí)現(xiàn)的步驟介紹的非常詳細(xì),需要的朋友可以參考下

1.前言

在Web系統(tǒng)中,一直以來(lái)權(quán)限都只是后端程序所控制的。因?yàn)閃eb 系統(tǒng)圍繞的是數(shù)據(jù),而和數(shù)據(jù)庫(kù)最緊密接觸的是后端程序。所以在很長(zhǎng)的一段時(shí)間內(nèi),權(quán)限一直都只是后端程序要考慮的話題。 但是隨著前后端分離架構(gòu)的流行,越來(lái)越多的項(xiàng)目也在前端進(jìn)行權(quán)限控制。

2.權(quán)限相關(guān)概念

2.1權(quán)限的分類(lèi)

(1)后端權(quán)限

從根本上講前端僅僅只是視圖層的展示,權(quán)限的核心是在于服務(wù)器中的數(shù)據(jù),所以后端才是權(quán)限的關(guān)鍵,后端權(quán)限可以控制某個(gè)用戶是否能夠查詢數(shù)據(jù),是否能夠修改數(shù)據(jù)等操作。

ps:后端如何知道該請(qǐng)求是哪個(gè)用戶發(fā)過(guò)來(lái)的

  • cookie
  • session
  • token

ps:后端的權(quán)限設(shè)計(jì)RBAC(一般五張表)

  • 用戶
  • 角色
  • 權(quán)限
  • 還有兩張關(guān)系表

(2)前端權(quán)限

本質(zhì)上來(lái)說(shuō),前端權(quán)限的控制就是控制前端的視圖層的展示和前端所發(fā)送的請(qǐng)求。但是只有前端權(quán)限控制沒(méi)有后端權(quán)限控制是萬(wàn)萬(wàn)不可的。 前端權(quán)限控制只是達(dá)到錦上添花的效果。

2.2前端權(quán)限的意義

如果僅從能夠修改服務(wù)器中數(shù)據(jù)庫(kù)中的數(shù)據(jù)層面上講,確實(shí)只在后端做控制就足夠了,那為什么越來(lái)越多的項(xiàng)目也進(jìn)行了前端權(quán)限的控制,主要有這幾方面的好處。

  • 降低非法操作的可能性;
  • 不怕贓偷就怕賊惦記,在頁(yè)面中展示出一個(gè)就算點(diǎn)擊了也最終會(huì)失敗的按鈕,勢(shì)必會(huì)增加有心者非法操作的可能性;
  • 盡可能排除不必要清求,減輕服務(wù)器壓力,沒(méi)必要的請(qǐng)求,操作失敗的清求,不具備權(quán)限的清求,這些應(yīng)該壓根就不需要發(fā)送,請(qǐng)求少了,自然也會(huì)減輕服務(wù)器的壓力;
  • 提高用戶體驗(yàn);
  • 根據(jù)用戶具備的權(quán)限為該用戶展現(xiàn)自己權(quán)限范圍內(nèi)的內(nèi)容,避免在界面上給用戶帶來(lái)困擾,讓用戶專注于分內(nèi)之事;

3.前端權(quán)限控制思路

3.1菜單的權(quán)限控制

在登錄請(qǐng)求中,會(huì)得到用戶的權(quán)限數(shù)據(jù),當(dāng)然,這個(gè)需要后端返回?cái)?shù)據(jù)的支持。前端根據(jù)權(quán)限數(shù)據(jù),展示對(duì)應(yīng)的菜單。點(diǎn)擊菜單,才能查看相關(guān)的界面。

3.2界面的權(quán)限控制

如果用戶沒(méi)有登錄,手動(dòng)在地址欄敲入登錄后主界面的地址,則需要跳轉(zhuǎn)到登錄界面。
如果用戶已經(jīng)登錄,如果手動(dòng)敲入非權(quán)限內(nèi)的地址,則需要跳轉(zhuǎn)404 界面。

3.3按鈕的權(quán)限控制

在某個(gè)菜單的界面中,還得根據(jù)權(quán)限數(shù)據(jù),展示出可進(jìn)行操作的按鈕,比如刪除、修改、增加等按鈕。

3.4接口的權(quán)限控制

如果用戶通過(guò)非常規(guī)操作,比如通過(guò)瀏覽器調(diào)試工具將某些禁用的按鈕變成啟用狀態(tài),此時(shí)發(fā)的請(qǐng)求也應(yīng)該被前端所攔截。

4.實(shí)現(xiàn)步驟

4.1菜單欄控制

用戶登錄之后,服務(wù)端返回一個(gè)數(shù)據(jù),這個(gè)數(shù)據(jù)有菜單列表和token,我們把這個(gè)數(shù)據(jù)放入到vuex中,然后主頁(yè)根據(jù)vuex中的數(shù)據(jù)進(jìn)行菜單列表的渲染。

問(wèn)題:刷新界面后vuex數(shù)據(jù)會(huì)消失,菜單欄會(huì)消失解決:將數(shù)據(jù)存儲(chǔ)在sessionStorage中,并讓其和vuex中的數(shù)據(jù)保持同步(用專門(mén)的持久化插件也可以)store/index.js:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    //每次點(diǎn)擊頁(yè)面中的刷新按鈕,state中的數(shù)據(jù)就會(huì)根據(jù)下面的數(shù)據(jù)重新初始化
    rightList: JSON.parse(sessionStorage.getItem('rightList') || '[]'),
    username: sessionStorage.getItem('username'),
  },
  mutations: {
    setRightList(state, newData) {
      state.rightList = newData
      sessionStorage.setItem('rightList', JSON.stringify(newData)) //sessionStorage只能存儲(chǔ)字符串
    },
    setUsername(state, newData) {
      state.username = newData
      sessionStorage.setItem('username', newData)
    },
  },
  actions: {},
  getters: {},
})

4.2界面的控制

登錄成功后,將token數(shù)據(jù)存儲(chǔ)在sessionStorage中,用來(lái)判斷是否登錄

(1)路由導(dǎo)航守衛(wèi)

router/index.js:

router.beforeEach((to, from, next) => {
      //頁(yè)面跳轉(zhuǎn)之前做攔截動(dòng)作,判斷token是否存在
      if (to.path === '/login') next()
      else {
        const token = sessionStorage.getItem('token')
        if (!token) next('/login')
        else {
          next()
        }
      }
    })

問(wèn)題:這樣用戶在登錄之后就可以訪問(wèn)其他界面了,但如果用戶A登錄之后只能訪問(wèn)a頁(yè)面不能訪問(wèn)b頁(yè)面,但是這時(shí)候他還是可以通過(guò)地址欄輸入進(jìn)入到b頁(yè)面。

解決:當(dāng)然我們也可以設(shè)置路由導(dǎo)航守衛(wèi),但是如果有多個(gè)頁(yè)面,設(shè)置會(huì)非常不方便,并且對(duì)于用戶A來(lái)說(shuō),它是不用訪問(wèn)b頁(yè)面的,這時(shí)候我們可以對(duì)A不顯示b頁(yè)面,這個(gè)時(shí)候我們就用到了動(dòng)態(tài)路由。

(2)動(dòng)態(tài)路由

根據(jù)當(dāng)前用戶所擁有的的權(quán)限數(shù)據(jù)來(lái)動(dòng)態(tài)添加所需要的路由。

先定義好所有的路由規(guī)則:router/routerMap.js:

import Users from '@/components/user/Users.vue'
import Roles from '@/components/role/Roles.vue'
import GoodsCate from '@/components/goods/GoodsCate.vue'
import GoodsList from '@/components/goods/GoodsList.vue'

const userRule = { path: '/users', component: Users }
const roleRule = { path: '/roles', component: Roles }
const goodRule = { path: '/goods', component: GoodsList }
const categoryRule = { path: '/categories', component: GoodsCate }

const routesMap = {
  users: userRule,
  roles: roleRule,
  goods: goodRule,
  categories: categoryRule,
}
export { routesMap }

登錄成功之后動(dòng)態(tài)添加路由,注意這個(gè)initDynamicRoutes的方法需要暴露出去在登錄頁(yè)面調(diào)用

這樣當(dāng)用戶A在地址欄輸入自己不能訪問(wèn)的路由時(shí),就不會(huì)跳轉(zhuǎn)到該頁(yè)面,而是跳轉(zhuǎn)到404頁(yè)面。

問(wèn)題:如果我們重新刷新的話動(dòng)態(tài)路由就會(huì)消失,動(dòng)態(tài)路由是在登錄成功之后才會(huì)調(diào)用,刷新的時(shí)候并沒(méi)有調(diào)用,所以動(dòng)態(tài)路由沒(méi)有添加上。

解決:可以在app.vue中的created中調(diào)用添加動(dòng)態(tài)路由的方法

4.3按鈕的控制

雖然用戶可以看到某些界面了,但是對(duì)于這個(gè)界面的一些按鈕,該用戶可能是沒(méi)有權(quán)限的。 因此,我們需要對(duì)組件中的一些按鈕進(jìn)行控制,用戶不具備權(quán)限的按鈕就隱藏或者禁用,而在這塊的實(shí)現(xiàn)中,可以把該邏輯放到自定義指令中

比如我們可以根據(jù)后端返回的數(shù)據(jù)right來(lái)判斷用戶有什么權(quán)限,如下圖。

添加自定義指令 控制按鈕

import Vue from 'vue'
import store from '../store';
import router from '../router';
const permission = {
  inserted(el, binding) {
    //傳過(guò)來(lái)的參數(shù)中,action表示被綁定的按鈕是什么操作;effect表示當(dāng)用戶沒(méi)有這個(gè)操作權(quán)限的時(shí)候,
    //應(yīng)該如何如理這個(gè)按鈕
    const action = binding.value.action
    const effect = binding.value.effect
    //獲取用戶在當(dāng)前路由中所具有的權(quán)限列表
    let currentPathPermissions = router.currentRoute.meta   
    if(currentPathPermissions.indexOf(action) == -1){
      if(effect === 'disabled'){
        el.disabled = true
        el.classList.add('is-disabled') //element-ui需要的處理
      }
      else
        el.parentNode.removeChild(el)
        //el.style.display = 'none'
    }
  }
}
Vue.directive('permission', permission)

4.4接口的控制

(1)請(qǐng)求控制

除了登錄請(qǐng)求都得要帶上token,這樣服務(wù)器才可以鑒別你的身份。這塊需要配置axios的請(qǐng)求攔截器。

如果發(fā)出了非權(quán)限內(nèi)的請(qǐng)求,應(yīng)該直接在前端范圍內(nèi)阻止,雖然這個(gè)請(qǐng)求發(fā)到服務(wù)器也會(huì)被拒絕。

非權(quán)限內(nèi)的請(qǐng)求:比如a用戶是不能夠操作該頁(yè)面的按鈕的,但是他通過(guò)f12調(diào)試把按鈕改為可點(diǎn)擊,如果我們不對(duì)這個(gè)請(qǐng)求進(jìn)行處理,那么這個(gè)請(qǐng)求就會(huì)發(fā)送出去。

//當(dāng)前模塊中具備的權(quán)限關(guān)系映射
const actionMapping = {
  get: 'view', //查看-->get請(qǐng)求
  post: 'add', //添加-->post請(qǐng)求
  put: 'edit', //編輯-->put請(qǐng)求
  delete: 'delete', //刪除-->delete請(qǐng)求
}
//請(qǐng)求攔截控制
axios.interceptors.request.use((request) => {
  // console.log(request.url);
  // console.log(request.method);
  if (request.url !== 'login') {
    //除了登錄請(qǐng)求以外,在請(qǐng)求頭中全部添加上token
    request.headers.Authorization = sessionStorage.getItem('token')
    //將請(qǐng)求方式映射成為操作類(lèi)型的權(quán)限
    const action = actionMapping[request.method]
    //獲取用戶在當(dāng)前路由下所具有的權(quán)限
    const currentRight = router.currentRoute.meta
    if (currentRight && currentRight.indexOf(action) === -1) {
      //沒(méi)有權(quán)限發(fā)送請(qǐng)求,通過(guò)報(bào)錯(cuò)攔截
      alert('沒(méi)有權(quán)限!')
      return Promise.reject(new Error('沒(méi)有權(quán)限'))
    }
  }
  return request
})

(2)響應(yīng)控制

得到了服務(wù)器返回的狀態(tài)碼401,代表token 超時(shí)或者被篡改了,此時(shí)應(yīng)該強(qiáng)制跳轉(zhuǎn)到登錄界面。

axios.interceptors.response.use((response) => {
  if (response.data.meta.status === 401) {
    //返回401表示token失效,返回登陸界面
    router.push('/login')
    sessionStorage.clear()
    window.location.reload()
  }
  return response
})

5.小結(jié)

  • 前端權(quán)限的實(shí)現(xiàn)必須要后端提供數(shù)據(jù)支持,否則無(wú)法實(shí)現(xiàn)。
  • 返回的權(quán)限數(shù)據(jù)的結(jié)構(gòu),前后端需要溝通協(xié)商怎樣的數(shù)據(jù)用起來(lái)才最方便。

5.1菜單控制

  • 權(quán)限的數(shù)據(jù)需要在多組件之間共享,因此采用vuex。
  • 防止刷新界面權(quán)限數(shù)據(jù)丟失,所以需要使用sessionStorage進(jìn)行持久化,并目要保證兩者的同步。

5.2界面控制

  • 路由的導(dǎo)航守衛(wèi)可以防止跳過(guò)登錄界面。
  • 動(dòng)態(tài)路由可以讓不具備權(quán)限的界面的路由規(guī)則壓根就不存在。

5.3按鈕控制

  • 路由規(guī)則中可以增加路由元數(shù)據(jù)meta。
  • 通過(guò)路由對(duì)象可以得到當(dāng)前的路由規(guī)則以及存在此規(guī)則中的meta數(shù)據(jù)。
  • 自定義指令可以很方便的實(shí)現(xiàn)按鈕控制。

5.4請(qǐng)求和響應(yīng)控制

  • 請(qǐng)求攔截器和響應(yīng)攔截器的使用。
  • 請(qǐng)求方式的約定restful。

總結(jié) 

到此這篇關(guān)于前端權(quán)限控制和管理實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)前端權(quán)限控制和管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • javaScript遍歷對(duì)象和數(shù)組的方法總結(jié)

    javaScript遍歷對(duì)象和數(shù)組的方法總結(jié)

    這篇文章介紹了javaScript遍歷對(duì)象和數(shù)組的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • 詳解webpack 入門(mén)總結(jié)和實(shí)踐(按需異步加載,css單獨(dú)打包,生成多個(gè)入口文件)

    詳解webpack 入門(mén)總結(jié)和實(shí)踐(按需異步加載,css單獨(dú)打包,生成多個(gè)入口文件)

    本篇文章主要介紹了webpack 入門(mén)總結(jié)和實(shí)踐(按需異步加載,css單獨(dú)打包,生成多個(gè)入口文件) ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • js顯示文本框提示文字的方法

    js顯示文本框提示文字的方法

    這篇文章主要介紹了js顯示文本框提示文字的方法,涉及javascript鼠標(biāo)事件及樣式操作的相關(guān)技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下
    2015-05-05
  • gulp-htmlmin壓縮html的gulp插件實(shí)例代碼

    gulp-htmlmin壓縮html的gulp插件實(shí)例代碼

    這篇文章主要介紹了gulp-htmlmin壓縮html的gulp插件實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2016-06-06
  • js+html獲取系統(tǒng)當(dāng)前時(shí)間

    js+html獲取系統(tǒng)當(dāng)前時(shí)間

    這篇文章主要為大家詳細(xì)介紹了javascript html獲取系統(tǒng)當(dāng)前時(shí)間,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • 9個(gè)JavaScript評(píng)級(jí)/投票插件

    9個(gè)JavaScript評(píng)級(jí)/投票插件

    在訪問(wèn)某個(gè)網(wǎng)站或者博客時(shí),如果該站點(diǎn)為用戶提供內(nèi)容的評(píng)級(jí)或投票功能的話,可以增強(qiáng)用戶參與的交互性之外,更可以給用戶一種“主人”的親切感,使得用戶可以切實(shí)地參與到網(wǎng)站內(nèi)容的評(píng)價(jià)體系中來(lái)。
    2010-01-01
  • 小程序開(kāi)發(fā)基礎(chǔ)之view視圖容器

    小程序開(kāi)發(fā)基礎(chǔ)之view視圖容器

    這篇文章主要介紹了小程序開(kāi)發(fā)基礎(chǔ)之view視圖容器,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • js實(shí)現(xiàn)煙花特效

    js實(shí)現(xiàn)煙花特效

    這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)煙花效果,實(shí)現(xiàn)鼠標(biāo)點(diǎn)擊出現(xiàn)模擬煙花爆炸的特效,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • js模擬點(diǎn)擊以提交表單為例兼容主流瀏覽器

    js模擬點(diǎn)擊以提交表單為例兼容主流瀏覽器

    我們會(huì)常常用到JS的模事件,比如說(shuō)點(diǎn)擊事件,舉個(gè)簡(jiǎn)單的例子,點(diǎn)擊表單外的“提交”按鈕來(lái)提交表單,下面為大家介紹下具體的實(shí)現(xiàn)
    2013-11-11
  • JavaScript中如何跳出forEach循環(huán)代碼示例

    JavaScript中如何跳出forEach循環(huán)代碼示例

    循環(huán)遍歷一個(gè)元素是開(kāi)發(fā)中最常見(jiàn)的需求之一,下面這篇文章主要給大家介紹了關(guān)于JavaScript中如何跳出forEach循環(huán)的相關(guān)資料,文章通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-06-06

最新評(píng)論