最近一段时间一直投入于对接合作伙伴的POC项目,虽然不是主要的开发人员,但是我需要对整个项目进行把控,涉及到的一些核心功能点也需要我去做一个把关。我们这边需要做一个OCR 文字识别的自定义模板配置平台,本不涉及到用户权限这块的内容,奈何客户爸爸执意要加,那好吧,我们就来做一个权限控制吧……
权限控制设计
其实大体上权限设计都是通过前后台协作一起完成,这个过程我们细致的分为:api访问权限控制 和 页面权限控制,进一步的细粒度区分,页面权限控制又包含页面是否能访问、页面中的按钮权限等等。我们一起看看这块功能的实现吧。
api 访问权限控制
实际上就是对用户信息的校验。在用户登录时服务器需要给前台返回一个Token,以后前台每次调用接口时都需要带上这个Token,服务端获取到这个Token后进行比对,如果通过则可以访问。现有的通常做法就是在登陆成功之后将后台返回的 Token 存储在前端缓存中,例如 sessionStorage,在请求时将 Token 取出来放在请求头 headers 中传给后台。下图以一个正常的请求数据接口作为示例代码:
this.httpRequest({
method: 'get',
url: 'test/query?id=llz',
withCredentials: true,
headers: {
token: sessionStorage.getItem('tokenKey') // 每次请求时都在headers 塞入 Token 信息
}
}).then(res => {
//请求成功后的操作
})
复制代码
后来axios 中可以在拦截器中直接塞入,作为全局传入,方便了很多(注意此时的Token 信息是同vuex 缓存中取到的,我们将在下一步展开)。
//main.js
import axios from 'axios'
// 实例化Axios,并进行超时设置
const instance = axios.create({
timeout: 5000
})
axios.defaults.baseURL = 'https://api.xxx.com';
// 每次请求都为http头增加Authorization字段,其内容为token;
instance.interceptors.request.use(
config => {
if (store.state.user.token) {
config.headers.Authorization = `token ${store.state.user.token}`; // vuex 缓存的Token信息塞入请求头
}
return config
},
err => {
return Promise.reject(err)
}
);
export default instance
复制代码
页面权限控制
我们针对页面访问权限展开讨论,我们希望实现一个效果:只显示当前用户能访问的权限内的菜单,当用户通过URL强制访问会直接进入 404 页面。针对此效果我们首先要做的就是配置好路由表信息。因为涉及到有些页面需要访问权限,有些页面不需要访问权限,所以我们将登录、404、维护等非权限操作页面写在默认路由,将其他权限操作页面写到一个变量中。(404 页面一定要最后加载,如果放在 constantRouterList 一同声明了404,后面的所以页面都会被拦截到404)
// router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import App from '@/App'
Vue.use(Router);
// 默认不需要权限的页面
const constantRouterList = [{
path: '/',
name: '登录',
component: (resolve) => require(['@/components/login'], resolve)
},
{
path: '/index',
name: '主页',
component: (resolve) => require(['@/components/index'], resolve)
},
{
path: '/template',
name: '模板页面',
component: (resolve) => require(['@/components/Template/template'], resolve)
}
]
// 注册路由
export const router = new Router({
routes: constantRouterList
});
// 需要权限控制的页面
export const asyncRouterList = [
{
path: '/resource',
name: 'Resource',
meta: {
permission: []
},
component: (resolve) => require(['@/components/Resource/resource'], resolve)
},
{
path: '',
name: 'Log',
component: App,
children: [{
path: '/userLog',
name: 'UserLog',
meta: {
permission: []
},
component: (resolve) => require(['@/components/Log/userLog'], resolve),
},
{
path: '/operatingLog',
name: 'operatingLog',
meta: {
permission: []
},
component: (resolve) => require(['@/components/Log/operatingLog'], resolve),
},
]
}
];
复制代码
页面访问的的大致流程我们可以用一下流程图表示:






















![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)