当前位置:   article > 正文

vue-admin-template登录以及权限使用

vue-admin-template登录

vue-admin-template是vue-element-admin的一个基础方案,很适合入门使用。
vue-element-admin官网
首先下载下来之后,

npm install
  • 1

在项目主目录运行该命令完成项目依赖的下载

npn run dev
  • 1

运行这个命令即可完成项目的运行。
下面介绍关于登录部分

自定义登录接口

该项目是通过login进行登录且每一次请求通过info请求进行验证用户身份,以及logout退出登录。
找到登录页面代码(src/views/login/index.vue)

 handleLogin() {
      this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true
          this.$store.dispatch('user/login', this.loginForm).then(() => {
            this.$router.push({ path: this.redirect || '/' })
            this.loading = false
          }).catch(() => {
            this.loading = false
          })
        } else {
          console.log('error submit!!')
          return false
        }
      })
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

这里会会找到user/login接口,原项目这里是通过mock创建的模拟数据,这里我们要改成我们的自定义后端接口(src/api/user.js)

export function login(data) {
  return request({
    url: '/user/login',
    method: 'post',
    data
  })
}

export function getInfo() {
  return request({
    url: '/user/info',
    method: 'get',
  })
}

export function logout() {
  return request({
    url: '/user/logout',
    method: 'get'
  })
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

这里login做的是关于登陆验证的,info用来获取用户信息,这里主要是用来获取权限的。
这里准备的是Java后台

public Result<Map> info(HttpServletRequest request) {
        User user = getByToken(request);
        ArrayList<String> roles = new ArrayList<>();
        Integer roleId = user.getRoleId();
        switch (roleId) {
            case 1:
                roles.add("admin");
                break;
        }
        Map<String, ArrayList> map = new HashMap<>();
        map.put("roles",roles);
        return Result.success(map);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这里将获取到的角色放到一个map中,返回给前台,注意我这里只返回了role,相当于我的data里只放了role。
登录就到此做完了,后面来做关于权限部分的东西。

路由权限控制

首先该项目的路由权限控制在路由js中通过role标签来控制的。(src/router/index.js)
对于一般的公共的路由,我们可以放在constantRoutes里

  export const constantRoutes = [
{
  path: '/login',
  component: () => import('@/views/login/index'),
  hidden: true
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

然后对于需要权限部分的路由,我们放在asyncRoutes里

//异步挂载的路由
//动态需要根据权限加载的路由表 
export const asyncRoutes  = [
{
  path: '/*******',
  component: Layout,
  children: [
    {
      path: 'index',
      name: '******',
      component: () => import('@/views/****/index'),
      meta: { title: '用户管理', icon: 'form',roles:['admin']}
    }
  ]
},
{ path: '*', redirect: '/404', hidden: true }
];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这里需要注意的是,404一定要放到最后

这里就完成了路由的权限制定,那么是怎么来确定用户身份,并动态显示的呢?
登录过程首先会执行store/modules/user.js的方法

const getDefaultState = () => {
  return {
    token: getToken(),
    name: '',
    //这里我只需要roles,所以就留了roles,这里注意是roles是一个数组,所以我后台也是对的map传过来的。
    roles:[]
  }
}

const state = getDefaultState()

const mutations = {
  RESET_STATE: (state) => {
    Object.assign(state, getDefaultState())
  },
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  SET_NAME: (state, name) => {
    state.name = name
  },
  //设置roles
  SET_ROLES: (state, roles) => {
    state.roles = roles
  }
}

const actions = {
  // user login
  login({ commit }, userInfo) {
    const { username, password } = userInfo
    return new Promise((resolve, reject) => {
      login({ username: username.trim(), password: password }).then(response => {
      //这里会请求到后台,后台返回用户名的名称,然后作为token存到cookie中,这一步看后台怎么写的,这里我是因为我每一个请求都要带token,后台做验证
        const { data } = response
        commit('SET_TOKEN', data)
        setToken(data)
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // get user info
  getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo(state.token).then(response => {
        const { data } = response

        if (!data) {
          return reject('Verification failed, please Login again.')
        }
		//上面提到我后台的info方法里就放了roles,所以这里是直接获取
        const {  roles } = data
		//设置roles
        commit('SET_ROLES', roles)
        resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  },

  // user logout
  logout({ commit, state }) {
    return new Promise((resolve, reject) => {
      logout(state.token).then(() => {
        removeToken() // must remove  token  first
        resetRouter()
        commit('RESET_STATE')
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77

这里的每一个方法,执行过程中都会去调用我们的api里的方法,去请求后台

然后在info请求中,需要在请求头里进行防止token,所以我们在项目提供的request.js里进行修改一下。(对应后台进行修改),把登录设置的token拿出来设置到请求头里

// request interceptor
service.interceptors.request.use(
  config => {
    // do something before request is sent

    if (store.getters.token) {
      // let each request carry token
      // ['X-Token'] is a custom headers key
      // please modify it according to the actual situation
      // config.headers['X-Token'] = getToken()
      //这里根据后台进行设置
      config.headers.Token = getToken();
    }
    return config
  },
  error => {
    // do something with request error
    console.log(error) // for debug
    return Promise.reject(error)
  }
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

这个是该项目封装的一个拦截器,每一次请求都会走它

每一次路由的改变都会触发src/permission.js 的beforeEach方法进行跳转
判断是否登录已经身份

router.beforeEach(async(to, from, next) => {
  // start progress bar
  NProgress.start()

  // set page title
  document.title = getPageTitle(to.meta.title)

  // determine whether the user has logged in
  const hasToken = getToken()

  if (hasToken) {
    if (to.path === '/login') {
      // if is logged in, redirect to the home page
      next({ path: '/' })
      NProgress.done()
    } else {
      const hasGetUserInfo = store.getters.name
      if (hasGetUserInfo) {
        next()
      } else {
        try {
          // get user info
          // await store.dispatch('user/getInfo')
          //从请求中获取到角色
          const { roles } = await store.dispatch('user/getInfo')
          console.log("获取到的roles"+roles)

          // generate accessible routes map based on roles
          //这里从permission/generateRoutes拿到路由
          const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
          //刷新路由
          router.options.routes = store.getters.permission_routes
          // dynamically add accessible routes
          router.addRoutes(accessRoutes)

          // next({...to,replace:true})
          next()
        } catch (error) {
          // remove token and go to login page to re-login
          await store.dispatch('user/resetToken')
          Message.error(error || 'Has Error')
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
  } else {
    /* has no token*/

    if (whiteList.indexOf(to.path) !== -1) {
      // in the free login whitelist, go directly
      next()
    } else {
      // other pages that do not have permission to access are redirected to the login page.
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

上面有一个步骤是从permission/generateRoutes拿到路由(src/store/module/permission.js)

import { asyncRoutes, constantRoutes } from '@/router'

/**
 * Use meta.role to determine if the current user has permission
 * @param roles
 * @param route
 */
function hasPermission(roles, route) {
  if (route.meta && route.meta.roles) {
    return roles.some(role => route.meta.roles.includes(role))
  } else {
    return true
  }
}

/**
 * Filter asynchronous routing tables by recursion
 * @param routes asyncRoutes
 * @param roles
 */
export function filterAsyncRoutes(routes, roles) {
  const res = []

  routes.forEach(route => {
    const tmp = { ...route }
    if (hasPermission(roles, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
  })

  return res
}

const state = {
  routes: [],
  addRoutes: []
}

const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes
    state.routes = constantRoutes.concat(routes)
  }
}

const actions = {
  generateRoutes({ commit }, roles) {
    return new Promise(resolve => {
      let accessedRoutes
      if (roles.includes('admin')) {
      //路由是否有admin,有直接全部显示
        accessedRoutes = asyncRoutes || []
      } else {
      //accessedRoutes这个就是当前角色可见的动态路由
        accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
      }
      commit('SET_ROUTES', accessedRoutes)
      resolve(accessedRoutes)
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

该文件该基础项目应该是没有的,需要自己创建,创建之后还要在module下的index.js进行注册

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'
import permission from '@/store/modules/permission'

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    app,
    settings,
    user,
    permission
  },
  getters
})

export default store
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

不然会爆找不到modules/permission的错误

最后就是怎么拿到路由和role
在module下的getter.js文件添加两行

const getters = {
  sidebar: state => state.app.sidebar,
  device: state => state.app.device,
  token: state => state.user.token,
  avatar: state => state.user.avatar,
  name: state => state.user.name,
  //添加以下两行
  roles: state =>state.user.roles,
  permission_routes: state=>state.permission.routes
}
export default getters
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

自此,一个简单的路由权限动态显示就完成了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/400789
推荐阅读
相关标签
  

闽ICP备14008679号