基于admin-template模板请求头带上Token

Posted 捡黄金的少年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于admin-template模板请求头带上Token相关的知识,希望对你有一定的参考价值。

实现逻辑如下

1、对于每次请求数据,从cookie中取token并赋值到请求头上(headers.Authorization)

2、对后端返回的数据,如果返回401,则通过存储在cookie中的刷新令牌(refreshTokenKey)来刷新token值,(一般而言token有效期7天或者一天,刷新令牌比token存放的久)

3、如果刷新令牌存在,则通过刷新令牌,重新获取用户信息,包括,token,userInfo(用户信息),refreshToken(刷新令牌)

4、如果刷新令牌不存在,则重新登录

(刷新页面,Vuex状态变成初始值)

发送请求

service.interceptors.request.use(
  config => 
    //  获取token
    const accessToken = PcCookie.get(Key.accessTokenKey)

    if (accessToken) 
      // 如果有token,则通过请求头添加
      config.headers.Authorization = `Bearer $accessToken`
      // 也可以使用下面这种
      // config.headers['Authorization'] = `Bearer $accessToken`

      // 后台接收的key:Authorization value值: Bearer $accessToken

    
    return config
  ,
  error => 
    // do something with request error
    console.log(error) // for debug
    return Promise.reject(error)
  
)

接收后台返回数据

service.interceptors.response.use(

  response => 
    const res = response.data

    // if the custom code is not 20000, it is judged as an error.
    if (res.code !== 20000) 
   //写正常返回逻辑
  ,
  error => 
    console.log('err' + error) // for debug

    // 判断状态
    if (error.response && error.response.status !== 401) 
      Message(
        message: error.message,  
        type: 'error',
        duration: 5 * 1000
      )
      return Promise.reject(error)
     
    // 如果是401未认证,则通过刷新令牌获取状态信息
    let isLock = true//防止重复提交
    if (isLock && PcCookie.get(Key.refreshTokenKey)) 
      isLock = false
      // 跳转到统一认证终端。实现令牌刷新token的效果
      window.location.href = `$process.env.VUE_APP_AUTH_CENTER_URL/refesh?/redirectURL=$window.location.href`
     else 
      // 如果刷新令牌没有,则进入登录页面
      window.location.href = `$process.env.VUE_APP_AUTH_CENTER_URL/login?/redirectURL=$window.location.href`
    

  
)

以上已经实现请求时候带上token值

Vuex菜单,按钮权限状态管理 

vuex 权限菜单集合,根据 vuex 中可访问的菜单,渲染侧边栏组件

创建menu.js

在store下面的module文件夹下面创建menu.js文件如下

// 请求用户权限接口API
import  getUserMenuList  from "@/api/user"

import  PcCookie, Key  from '@/utils/cookie'
const state = 
    init: false,//是否已经加载用户权限
    menuList: [],//用户拥有的菜单权限
    buttonList: [],//用户拥有的按钮权限

const mutations =  //改变状态值
    SET_SYSTEM_MENU: (state, data) => 
        state.init = true//已经加载用户权限
        state.menuList = data.menuTreeList//保存菜单权限
        state.buttonList = data.buttonList//保存按钮权限
    


// 定义行为
const actions = 
    GetUserMenu( commit ) 
        // reslove正常返回结果,reject异常返回结果
        return new Promise((reslove, reject) => 
            //获取用户ID
            const userId = PcCookie.get(Key.userInfoKey) ? JSON.parse(PcCookie.get(Key.userInfoKey)).uid : null
            // 发送请求获取权限信息
            if (userId) 
                getUserMenuList(userId).then(response => 
                    // 将获取到的菜单按钮数据信息,存放到Vuex进行状态管理
                    commit('SET_SYSTEM_MENU', response.data)
                    reslove()
                ).catch(error => 
                    // 返回异常对象
                    reject()
                )
            

        )
    

export default 
    namespaced: true,//引用需要的模块名称 /menu/GetUserMenu
    state,
    mutations,
    actions

在getters.js中引入state中定义的几个状态,外面使用方式 $store.getters.buttonList

const getters = 
 ........
  // 添加菜单相关状态
  init: state => state.menu.init,
  menuList: state => state.menu.menuList,
  buttonList: state => state.menu.buttonList

export default getters

在index,js中引入menu.js给vuex状态管理

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import app from './modules/app'
import settings from './modules/settings'
import user from './modules/user'
// tagsView
import tagsView from './modules/tagsView'
// 
import menu from './modules/menu'

Vue.use(Vuex)

const store = new Vuex.Store(
  modules: 
    app,
    settings,
    user,
    tagsView,
    menu
  ,
  getters
)

export default store

 

在permission中对,存在token值且没有拿取到菜单,按钮的信息,就调用 store.dispatch('menu/GetUserMenu')方法进行拿取,只要不刷新页面,vuex就会存在菜单按钮信息,通过store.getters.init 判断,就不用每次请求路由都调用(刷新页面置空Vuex数据)

const hasGetUserInfo = PcCookie.get(Key.accessTokenKey)
      if (hasGetUserInfo) 
        // 如果有用户信息,则通过用户ID来查询当前用户的菜单和按钮权限

        if (store.getters.init === false) 

          // 还没有查询用户信息,开始查询用户信息
          //因为我们采用namespaced: true,所以需要
          store.dispatch('menu/GetUserMenu').then(() => 
            //继续访问目标路由,且不会留下history记录
            next( ...to, replace: true )
          ).catch(error => 
            Message(
              message: "获取用户信息失败",
              type: "error"
            )
          )
         else 
          // 跳转到目标路由
          next()
        

通过Vuex中的管理的数据,动态渲染左边的菜单组件


  <sidebar-item v-for="menu in menuList" :key="menu.id" :item="menu"  />

import  mapGetters  from 'vuex'
export default 
  components:  SidebarItem, Logo ,
  computed: 
    ...mapGetters([
      'sidebar',
      'menuList'//获取menuList中的状态值,menuList
    ]),
 <div>
    <!-- 没有子菜单,只有一级菜单 -->
    <template v-if="!item.children || item.children.length === 0">
      <app-link :to="item.url">
        <el-menu-item
          :index="item.url"
          :class=" 'submenu-title-noDropdown': !isNest "
        >
          <item :icon="item.icon" :title="item.name" />
        </el-menu-item>
      </app-link>
    </template>
    <!-- 有子菜单 -->
    <el-submenu v-else ref="subMenu" :index="item.id" popper-append-to-body>
      <template slot="title">
        <item :icon="item.icon" :title="item.name" />
      </template>
      <sidebar-item
        v-for="child in item.children"
        :key="child.id"
        :is-nest="true"
        :item="child"
        
        class="nest-menu"
      />
      <!-- :base-path="resolvePath(child.path)" -->
    </el-submenu>
  </div>

以上是关于基于admin-template模板请求头带上Token的主要内容,如果未能解决你的问题,请参考以下文章

基于admin-template模板,实现按钮权限管理

SpringBoot Feign内部调用时自动带上请求头信息(header)

SpringBoot Feign内部调用时自动带上请求头信息(header)

SpringBoot Feign内部调用时自动带上请求头信息(header)

API安全设计

如何书写带token的请求头。