이 글은 Vue에서 백그라운드 관리 시스템의 권한 제어를 구현하는 방법에 대한 것입니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
광고기계 프로젝트에서 역할 권한 관리는 오랫동안 정체되어 있던 어려운 점이었습니다. 우선, 우리가 결정한 권한 제어는 두 부분으로 나뉘는데, 그 부분은 granule의 크기에 따라 더 자세히 설명됩니다.
인터페이스 액세스에 대한 권한 제어#🎜 🎜##🎜🎜 #
# 🎜🎜#
페이지에 있는 버튼의 권한 제어(추가, 삭제, 수정)가 표시되는지 여부인터페이스 권한은 사용자에 대한 확인입니다. 일반적으로 사용자가 로그인하면 서버는 토큰을 프런트 데스크에 반환해야 하며 프런트 데스크는 인터페이스를 호출할 때마다 이 토큰을 가져와야 합니다.
기존 방법은 로그인 성공 콜백에서 백그라운드에서 반환된 토큰을 sessionStorage
에 직접 저장했다가 로그인 성공 시 토큰을 꺼내서 헤더에 넣는 것이었습니다. 요청하고 백그라운드로 전달하면 코드는 다음과 같습니다:
this.$http({ method: 'get', url: 'test/query?id=20', withCredentials: true, headers: { token: sessionStorage.getItem('token'), name: sessionStorage.getItem('name') //应后台需求传的用户名 } }).then(response => { //请求成功后的操作 })
나중에 일부 기사에서 axios가 토큰을 config.headers.Authorization
에 직접 삽입할 수 있다는 것을 발견했습니다. 인터셉터에서 전역 패스로 사용됩니다. 코드 부분은 다음과 같습니다.
//main.js import axios from 'axios' // 实例化Axios,并进行超时设置 const service = axios.create({ timeout: 5000 }) // baseURL // axios.defaults.baseURL = 'https://api.github.com'; // http request 拦截器 // 每次请求都为http头增加Authorization字段,其内容为token service.interceptors.request.use( config => { if (store.state.user.token) { config.headers.Authorization = `token ${store.state.user.token}`; } return config }, err => { return Promise.reject(err) } ); export default service
3. 페이지 권한 제어 sessionStorage
,然在请求时将Token取出放入headers中传给后台,代码如下:
// router/index.js import Vue from 'vue' import Router from 'vue-router' import App from '@/App' import store from '../store/index' Vue.use(Router); //手动跳转的页面白名单 const whiteList = [ '/' ]; //默认不需要权限的页面 const constantRouterMap = [ { path: '/', name: '登录', component: (resolve) => require(['@/components/login'], resolve) }, { path: '/index', name: 'nav.Home', component: (resolve) => require(['@/components/index'], resolve) }, { path: '/templateMake', name: '模板制作', component: (resolve) => require(['@/components/Template/templateMake'], resolve) }, { path: '/programMack', name: '节目制作', component: (resolve) => require(['@/components/Template/programMack'], resolve) }, { path: '/release', name: '节目发布', component: (resolve) => require(['@/components/Program/release'], resolve) } ] //注册路由 export const router = new Router({ routes: constantRouterMap }); //异步路由(需要权限的页面) export const asyncRouterMap = [ { path: '/resource', name: 'nav.Resource', meta: { permission: [] }, component: (resolve) => require(['@/components/Resource/resource'], resolve) }, { path: '/template', name: 'nav.Template', meta: { permission: [] }, component: (resolve) => require(['@/components/Template/template'], resolve) }, { path: '/generalSet', name: 'nav.System', meta: { permission: [] }, component: (resolve) => require(['@/components/SystemSet/generalSet'], resolve) }, { path: '', name: 'nav.Log', component: App, children: [ { path: '/userLog', name: 'nav.UserLog', meta: { permission: [] }, component: (resolve) => require(['@/components/Log/userLog'], resolve), }, { path: '/operatingLog', name: 'nav.SystemLog', meta: { permission: [] }, component: (resolve) => require(['@/components/Log/operatingLog'], resolve), }, ] } ] ];
后来在一些文章中发现axios可以在拦截器中直接将Token塞入config.headers.Authorization
이 권한은 일반적으로 고정된 페이지에서 구성한 후 데이터베이스에 저장하고 기록합니다
사용자가 접근하지 않는 메뉴를 모두 표시합니다. 자신의 권한 내에서 권한이 부족하다는 메시지가 표시됩니다
현재 사용자가 접근할 수 있는 권한 내에서만 메뉴를 표시합니다. URL은 404를 직접 입력합니다
이제 표시되는데 나왔는데 클릭이 안되면 그냥 놀리는 건가요? ? 속담처럼, 눈에 띄지 않는 것은 마음에 들지 않습니다. 종합적으로 고려한 후에는 옵션 2가 확실히 좋은 사용자 경험에 더 부합합니다.
이후 그 과정을 정리하고 자세하게 작성하기 시작했습니다. 1. 라우팅 테이블 만들기
라우팅 테이블을 만드는 것은 사실 어렵지 않습니다. vue-router 공식 문서에 나와 있는 예제를 따라 직접 작성해 보세요. 다만,
효과적으로 후속 유지 관리 부담을 줄일 수 있습니다.
아래에 index.js 코드를 붙여넣을 예정입니다. 너무 많은 공간을 차지하지 않도록 비동기 라우팅이 적절하게 줄어들 것입니다.
// store/index.js import Axios from 'axios' import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); const axios = Axios.create(); const state = { mode: 'login', list: [] }; const getters = {}; const mutations = { setMode: (state, data) => { state.mode = data }, setList: (state, data) => { state.list = data } }; const actions = { // 获取权限列表 getPermission({commit}) { return new Promise((resolve, reject) => { axios({ url: '/privilege/queryPrivilege?id=' + sessionStorage.getItem('privId'), methods: 'get', headers: { token: sessionStorage.getItem('token'), name: sessionStorage.getItem('name') } }).then((res) => { // 存储权限列表 commit('setList', res.data.cust.privileges[0].children); resolve(res.data.cust.privileges[0].children) }).catch(() => { reject() }) }) } }; export default new Vuex.Store({ state, mutations, actions, getters })
참고: 여기서 특별한 주의가 필요한 한 가지는 404 페이지가 마지막에 로드되어야 한다는 것입니다. 404가 ConstantRouterMap과 함께 선언되면 모든 후속 페이지가 가로채어 404를 받게 됩니다. 자세한 질문은 다음을 참조하세요. 404에 대한 와일드카드 경로가 있는 경우 addRoutes가 작동하지 않습니다
2. 페이지 액세스 권한
처음에는 대략적인 페이지 액세스 권한 프로세스를 정리했습니다. 먼저 핵심 부분을 구현해 보겠습니다.
먼저 사용자 권한 목록을 가져오고 여기서 Vuex 상태 관리를 터치합니다. , 공식 문서에는 자세한 소개가 있으므로 여기서는 너무 많이 설명하지 않겠습니다. 아래 코드를 살펴보십시오. // router/index.js
/**
* 根据权限匹配路由
* @param {array} permission 权限列表(菜单列表)
* @param {array} asyncRouter 异步路由对象
*/
function routerMatch(permission, asyncRouter) {
return new Promise((resolve) => {
const routers = [];
// 创建路由
function createRouter(permission) {
// 根据路径匹配到的router对象添加到routers中即可
permission.forEach((item) => {
if (item.children && item.children.length) {
createRouter(item.children)
}
let path = item.path;
// 循环异步路由,将符合权限列表的路由加入到routers中
asyncRouter.find((s) => {
if (s.path === '') {
s.children.find((y) => {
if (y.path === path) {
y.meta.permission = item.permission;
routers.push(s);
}
})
}
if (s.path === path) {
s.meta.permission = item.permission;
routers.push(s);
}
})
})
}
createRouter(permission)
resolve([routers])
})
}
자, 이제 권한 데이터를 가져오고 저장하기 위한 배경을 요청합니다. vuex의 데이터, 아래에서는 반환된 데이터를 사용하여 이전에 작성된 비동기 라우팅 테이블과 일치하고 일치하는 결과를 정적 라우팅 테이블과 결합하여 최종 실제 라우팅 테이블을 생성해야 합니다.
가장 중요한 것은 vue-router2.2.0 버전에 새로 추가된 addRoutes 메소드를 사용하는 것입니다. 공식 문서에서 이 메소드를 어떻게 설명하는지 살펴보겠습니다.
router.addRoutes( 경로) 2.2.0+
더 많은 라우팅 규칙을 동적으로 추가합니다. 인수는 경로 옵션의 요구 사항과 일치하는 배열이어야 합니다. 이제 라우팅 일치를 위해 addRoutes를 사용할 수 있습니다. 아래 코드를 살펴보겠습니다.// router/index.js router.beforeEach((to, form, next) => { if (sessionStorage.getItem('token')) { if (to.path === '/') { router.replace('/index') } else { console.log(store.state.list.length); if (store.state.list.length === 0) { //如果没有权限列表,将重新向后台请求一次 store.dispatch('getPermission').then(res => { //调用权限匹配的方法 routerMatch(res, asyncRouterMap).then(res => { //将匹配出来的权限列表进行addRoutes router.addRoutes(res[0]); next(to.path) }) }).catch(() => { router.replace('/') }) } else { if (to.matched.length) { next() } else { router.replace('/') } } } } else { if (whiteList.indexOf(to.path) >= 0) { next() } else { router.replace('/') } } });
//异步路由(需要权限的页面) export const asyncRouterMap = [ { path: '/resource', name: 'nav.Resource', meta: { permission: [] }, component: (resolve) => require(['@/components/Resource/resource'], resolve) }, { path: '/template', name: 'nav.Template', meta: { permission: [] }, component: (resolve) => require(['@/components/Template/template'], resolve) }, { path: '/generalSet', name: 'nav.System', meta: { permission: [] }, component: (resolve) => require(['@/components/SystemSet/generalSet'], resolve) }, { path: '', name: 'nav.Log', component: App, children: [ { path: '/userLog', name: 'nav.UserLog', meta: { permission: [] }, component: (resolve) => require(['@/components/Log/userLog'], resolve), }, { path: '/operatingLog', name: 'nav.SystemLog', meta: { permission: [] }, component: (resolve) => require(['@/components/Log/operatingLog'], resolve), }, ] } ] ];
이 시점에서 페이지 액세스 권한 제어가 완료되었습니다. 작업 버튼에 대해 설명하겠습니다. 부분.
是否还记得前面的路由配置中我们多出来的一个代码,下面我们拿出来看看:
//异步路由(需要权限的页面) export const asyncRouterMap = [ { path: '/resource', name: 'nav.Resource', meta: { permission: [] }, component: (resolve) => require(['@/components/Resource/resource'], resolve) }, { path: '/template', name: 'nav.Template', meta: { permission: [] }, component: (resolve) => require(['@/components/Template/template'], resolve) }, { path: '/generalSet', name: 'nav.System', meta: { permission: [] }, component: (resolve) => require(['@/components/SystemSet/generalSet'], resolve) }, { path: '', name: 'nav.Log', component: App, children: [ { path: '/userLog', name: 'nav.UserLog', meta: { permission: [] }, component: (resolve) => require(['@/components/Log/userLog'], resolve), }, { path: '/operatingLog', name: 'nav.SystemLog', meta: { permission: [] }, component: (resolve) => require(['@/components/Log/operatingLog'], resolve), }, ] } ] ];
为每个路由页面增加meta字段。在routerMatch函数中将匹配到的详细权限字段赋值到这里。这样在每个页面的route对象中就会得到这个字段。
asyncRouter.find((s) => { if (s.path === '') { s.children.find((y) => { if (y.path === path) { //赋值 y.meta.permission = item.permission; routers.push(s); } }) } if (s.path === path) { s.meta.permission = item.permission; routers.push(s); } })
接下来我们编写一个vue自定义指令对页面中需要进行鉴权的元素进行判断,比如类似这样的:
<a></a> /* 3代表一个上传权限的ID,权限中有3则显示按钮 */
我们直接注册一个全局指令,利用vnode来访问vue的方法。代码如下:
//main.js //按扭权限指令 Vue.directive('allow', { inserted: (el, binding, vnode) => { let permissionList = vnode.context.$route.meta.permission; if (!permissionList.includes(binding.value)) { el.parentNode.removeChild(el) } } })
至此为止,权限控制流程就已经完全结束了,在最后我们再看一下完整的权限控制流程图吧.
위 내용은 Vue에서 백그라운드 관리 시스템 권한 제어를 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!