首页 > 解决方案 > 当用户在Vue中注销时重定向到登录页面

问题描述

我是 JS 和 VUE 的初学者。我在 Vue 和 Laravel 中制作迷你 CMS。我在 Vue 中创建了这个路由器:

import Vue from 'vue'
import Router from 'vue-router'

// Containers
const TheContainer = () => import('@/containers/TheContainer')

// Views
const Dashboard = () => import('@/views/Dashboard')
....

Vue.use(Router)

let router = new Router({
  mode: 'hash', // https://router.vuejs.org/api/#mode
  linkActiveClass: 'active',
  scrollBehavior: () => ({ y: 0 }),
  routes: configRoutes()
})


router.beforeEach((to, from, next) => {
  let roles = localStorage.getItem("roles");

  if(roles != null){
    roles = roles.split(',')
  }
  if(to.matched.some(record => record.meta.requiresAdmin)) {
    if(roles != null && roles.indexOf('admin') >= 0 ){
      next()
    }else{
      next({
        path: '/login',
        params: { nextUrl: to.fullPath }
      })
    }
  }else if(to.matched.some(record => record.meta.requiresUser)) {
    if(roles != null && roles.indexOf('user') >= 0 ){
      next()
    }else{
      next({
        path: '/login',
        params: { nextUrl: to.fullPath }
      })
    }
  }else{
    next()
  }
})

export default router

function configRoutes () { 
  return [
    {
      path: '/',
      redirect: '/dashboard',
      name: 'Home',
      component: TheContainer,
      children: [
        {
          path: 'dashboard',
          name: 'Dashboard',
          component: Dashboard
        },
          ]
        },
  ]
}

它工作正常,但我有两个问题:

  1. 当用户未登录时 - 然后我需要重定向到我的登录页面 (/login) - 而不是 /dashboard
  2. 当用户会话过期时 - 然后重定向到登录页面

如果用户登录 - 那么第一页(和主页)是 /dashboard

我怎样才能做到?

请帮我。

标签: javascriptvue.js

解决方案


你觉得这怎么样:

import Vue from 'vue'
import Router from 'vue-router'

// Containers
const TheContainer = () => import('@/containers/TheContainer')

// Views
const Dashboard = () => import('@/views/Dashboard')
// ....

Vue.use(Router)

let router = new Router({
  mode: 'hash', // https://router.vuejs.org/api/#mode
  linkActiveClass: 'active',
  scrollBehavior: () => ({ y: 0 }),
  routes: configRoutes()
})

// routing logic for not-logged-in
// users with a role
const useToLoginObj = (to) => ({
  path: '/login',
  params: {
    nextUrl: to.fullPath
  }
})

// DON'T DO THIS IN PRODUCTION!
// secure/security info should
// **NEVER** BE SAVED TO LOCALSTORAGE!!!!!
const fetchUserRoles = () => {
  const roles = localStorage.getItem("roles")?.split(',')
  return roles
}

// possible roles as keys
// corresponding required meta as value
const rolesDict = {
  admin: 'requiresAdmin',
  user: 'requiresUser',
}

const getRequiredRole = ({ to, rolesDict }) => {
  let requiredRole = null

  for (let key in roles) {
    // if the required role is already set, then
    // don't do anything
    if (!requiredRole && to.matched.some(record => record.meta[rolesDict[key]])) {
      requiredRole = key
    }
  }
  // if no role is required, then the
  // return value is null (falsy)
  return requiredRole
}

// if fetched roles include the requiredRole
const routeAuthUser = ({ roles, requiredRole, toLogin, next }) => {
  if (!roles.includes(requiredRole)) {
    next(toLogin)
  } else {
    next()
  }
}

router.beforeEach((to, from, next) => {
  const requiredRole = getRequiredRole({to, rolesDict})

  // if requiredRole is falsy (this route
  // doesn't require a role), then go
  if (!requiredRole) {
    next()
  } else {
    const roles = fetchUserRoles()
    const toLogin = useToLoginObj(to)

    // if no roles are there, then go to login
    if (!roles || !roles.length) {
      next(toLogin)
    } else {
      // user is routed based on her/his role
      routeAuthUser({ roles, requiredRole, toLogin, next })
    }
  }
})

比有问题的代码更详细,但是

  • 步骤被分解,因此逻辑更好地闪耀
  • 路由步骤的顺序beforeEach更合乎逻辑(“错误优先”方法)

我无法尝试,因此代码中可能存在错误,但逻辑(我认为)很清楚:将其分解为小块,然后从这些小块构建您想要的逻辑。

建议

尝试寻找不同的解决方案来存储用户角色。localStorage是安全数据的最不安全(甚至称其为“最不安全”是夸大其词)的解决方案。


推荐阅读