登录机制

325 阅读2分钟

具体步骤:

  • 首次登录,将用户名密码传给后端,返回token
  • token存储在localStroageVuex中。
  • Axiostoken写入请求头中。
  • 前端每次请求接口都将携带token信息。
  • 后端判断token是否过期,过期或者没有,则返回401。
  • 前端根据401状态码,将页面重定向到登录页面中。

封装LocalStorage

const TokenKey = 'packet_token'

export function getToken() {
  return localStorage.getItem(TokenKey)
}

export function setToken(token) {
  return localStorage.setItem(TokenKey, token)
}

export function removeToken() {
  return localStorage.removeItem(TokenKey)
}

封装非常简单,封装三个方法getTokensetTokenremoveToken

  • 登录时,调用setToken将token值存储到localStorage中
  • 请求接口时,调用getToken将token值放在请求头中。
  • token过期时,调用removeToken将localStorage中的token移除。

封装Axios

然后配置请求拦截器,目的是为了将每个请求都写入一个packet_tokenheader

server.interceptors.request.use(request => {
  request.headers['packet_token'] = getToken()
  return request
}, error => {
  return Promise.reject(error)
})

接着配置响应拦截器,目的是拦截401状态码。

如果出现401状态码,就调用removeToken删除localStorage中的token并刷新页面。

server.interceptors.response.use(response => {
  return response
}, error => {
  if (error.response.status === 401) {
    removeToken()
    location.reload()
  }
  return Promise.reject(error)
})

路由处理

访问登录之外的页面,都需要登录权限。比如首页,判断是否存在token,有就访问成功,没有则跳转到登录页面。

页面路由跳转过程中,会使用全局钩子router.beforeEach中拦截路由,检测到没有token就重定向至登录页面。

 router.beforeEach((to, from, next) => {
        if (localStorage.getItem('packet_token') === null && to.path !== '/login') {
            next({ path: '/login' })
        }
        next()
    })

大致上,登录功能就已经完成了。

权限

有登录必有权限,有些页面只有管理员才能访问,有些页面所有人都能访问。那怎么处理比较好呢?

路由级别的权限,我建议前端自己来配置,要不然,在开发阶段,每增加一个路由就要后端去配置,简直是噩梦。

具体实现:

  • 在挂载router时,先将一些公用页面挂载,比如说登录页面。
  • 当用户登录后,获取到用户角色的权限,再将其权限与路由表中每个页面所需的权限作一次比较,生成用户最终的路由表。
  • 调用router.addRouter()方法将其路由表添加到vue-router中。
// router.js
export const normalRoutes = [
    {
        path: '/login',
        name: 'login'
        component: Login
    },
    {
        path: '/',
        name: '首页'
        component: Index
    }
]

export const asyncRouters = [
    {
        path: '/edit',
        name: '编辑页面',
        component: Edit,
        role: {
            role: ['admin, 'editor']
        }
    },
    ...
    {
        path: '*',
        redirect: '/404'
    }
]

注意:404页面一定要最后加载,如果放在normalRoutes中,后面的路由访问都将会被拦截到404

 router.beforeEach((to, from, next) => {
        if (localStorage.getItem('packet_token') === null && to.path !== '/login') {
            next({ path: '/login' })
        } else {
            // 请求用户权限信息
            // 生成可访问的路由表
            next();
        }
        next()
    })