vue权限——接口权限详解,关于token

392 阅读4分钟

什么叫权限

权限是对特定资源的访问许可,所谓的权限控制,也就是确保用户只能访问到被分配的资源。
前端权限归根结底是请求的发起权,请求的发起一般有下面两种情况:

  • 页面加载时触发
  • 点击页面上的按钮触发 总的来说,所有的请求发起都触发自前端路由或视图

前端权限控制可以分为四个方面:

  • 接口权限
  • 按钮权限
  • 菜单权限
  • 路由权限 今天,我们主要来看一看接口权限

一,接口权限

当用户需要访问数据发送请求时,通常都得获取token密匙,只有通过token的验证,用户才能访问页面,若是没有token或者token失效,都会跳转登陆页进行重新获取,并在控制台打印401错误。
因为用户的token都是在登录的时候获取,所在登录页和注册页访问接口数据时,不需要token值,并且在用户点击登录时从接口获取token值保存在本地中。 如果项目较大,需要用到vuex,建议将token值存放在vuex中,代码如下:
01,定义函数发送请求

 actions: {
    //用户点击登录  获取token值
   async userLogin(context,token){
      const res = await login(token)
      // console.log(res)
      context.commit('setToken',res.data)
    },}

02,获取token并储存到state中

    mutations: {
    // 获取token值
    setToken(state,newToken){
        state.token = newToken
        }

03,定义空token,接收token值并储存

state:()=>{
    return {
      //保存token
      token: '',
    }
  },

04,登录页调用userLogin函数并传参,参数为用户账号与密码,注释部分为直接在登录页获取token

async dologin(){
      try{
       await this.$store.dispatch('user/userLogin',this.loginForm)
        // const res = await login(this.loginForm)
        // // console.log(res.data)
        // // 将token值传给mutations
        // //前面记得加模块名user
        // this.$store.commit('user/setToken',res.data)
        const return_url = this.$route.query.return_url || ''
        this.$router.push(return_url)
      }catch(err){
          alert(err)
      }
    },

注意:在登录页加async和await,是为了让登录页dologin里面的代码同步执行,如果不加,代码运行时不会等待调用actions里面的函数传值回来
另外,以上代码只是获取了token,页面一刷新,token就没了,所以我们需要将token保存在本地,有三种方法可以实现:

  1. 使用本地存储来实现
 localStorage.setItem('token',res.token)//储存
  // 存储共享数据的对象,取出在保存
  state: {
    // 存储token值
    token: localStorage.getItem('token') || ''
  },
  1. 使用插件vuex-persistedstate实现持久化存储 运行如下命令,安装持久化存储 vuex 中数据的第三方包
npm install --save vuex-persistedstate@3.2.1

src/store/index.js 模块中,导入并配置 vuex-persistedstate

import Vue from 'vue'
import Vuex from 'vuex'
// 1. 导入包
import createPersistedState from 'vuex-persistedstate'

Vue.use(Vuex)

export default new Vuex.Store({
  // 2. 配置为 vuex 的插件
  plugins: [createPersistedState()],
  state: {
    token: ''
  },
  mutations: {
    updateToken(state, newToken) {
      state.token = newToken
    }
  }
})

  1. 运用工具方法js-cookie
import Cookies from 'js-cookie'
const TokenKey = 'hrsaas-ihrm-token' // 设定一个独一无二的key
export function getToken() {
  return Cookies.get(TokenKey)
}

export function setToken(token) {
  return Cookies.set(TokenKey, token)
}

export function removeToken() {
  return Cookies.remove(TokenKey)
}

在mutations调用setToken(newToken)函数,传参为token

 mutations: {
    // 获取token值
    setToken(state,newToken){
        state.token = newToken

        // 调用封装好的函数,做持久化 获取token
        setToken(newToken)
    }
  },

在state取出token

state:()=>{
    return {
      //保存token
      // 如果本地有token,就用本地的,如果没有,就为空
      token:  getToken() || '',
    }
  },

注意:在state中储存token有两种状态,一种是还未获取token时,值为空,一种是获取了token保存到了本地,用本地中的token,本地有限

在运用以上方式获取token成功之后,接下来,还需要对其进行一些优化。
首先,我们获取token的目的是为了访问后续接口
所以后续接口都需要token值
这样,我们就可以将token值直接存放在请求拦截器中
只要发起了请求,就可以自动获取token
代码如下:

// 添加请求拦截器
service.interceptors.request.use(function (config) {
  // 在发送请求之前做些什么获取token值
  const token = store.state.user.token
  // console.log(token)
  //判断:如果有token值,就将token赋值给请求头,注意,右边的值以后端需求为主
  if(token){
    config.headers.Authorization = `Bearer ${token}`
  }
  return config;
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error);
});

其次,获取token有两种状态,成功与失败,当获取token失败时,应当抛出这个错误,而且,当token失效时,页面应该自动跳转登录页进行重新获取:

// 响应拦截器
service.interceptors.response.use(response => {
  //获取数据失败,但是响应码却是2开头,不报错,需要主动抛出错误
  if (response.data.success === false) {
    // 操作成功
    return Promise.reject(response.data.Message)
  } 
  // console.log(response)
  //对后端返回的数据进行脱壳处理
  return response.data
}, error => {
//token失效,响应码为10002,清除token与用户信息,并进行跳转
  if(error.response.data.code === 10002){
    store.dispatch('user/logout')
    router.push('/login?return_url=' + encodeURIComponent(router.currentRoute.fullPath))
  }
  return Promise.reject(error) // 返回执行错误 让当前的执行链跳出成功 直接进入 catch
})

以上就是接口权限的所有内容,接口权限,主要就是获取token值,对token值的一些优处理,虽然并不复杂,但是也有很多细节。