登录鉴权
前端执行登录获得并保存token,在发送需要登录权限的请求时携带token。
整体流程:
- 如果用户未登录,当用户使用那些需要登录权限的功能时,跳转到登录页。
- 登录成功后,用户再次使用那些需要鉴权的功能时,就不会被拦截了。
- 另外,一般后端也会有鉴权,如果用户需要调用一些有权限的接口时,在请求拦截器中添加token传递给后端,后端就知道我的身份了。
将token保存在vuex中
vue项目刷新瞬间保存在WebStorage中,再从WebStorage获取并重新保存,避免登录状态被清除
按页面效果分为路由鉴权和功能鉴权
路由鉴权
思路:使用VueRouter的路由守卫和meta信息记录,路由守卫根据
// 路由
// meta中有是否需要鉴权的判断
const router = new VueRouter({
mode: 'hash',
routes: [
{ path: '/', component: Home },// 不需要鉴权
{ path: '/good/detail/:id', component: Detail },// 商品详情不需要鉴权
{ path: '/cart', component: Cart, meta:{ isAuth:true }}, // 购物车需要鉴权
{ path: '/user', component: User, meta:{ isAuth:true } }, // 用户信息需要鉴权
{ path: '/login', component: Login },
{ path: '/regist', component: Regist }
]
})
// 路由守卫
router.beforeEach((to,from,next)=>{
const { isAuth } = to.meta
// 假设的一个登录标识
const token = store.state.user.token
if (isAuth) {
// 需要登录,才能过去
if (token) next()
else router.push('/login')
// else location.href = '#/login'
} else {
next()
}
})
功能鉴权
比如商品详情中添加购物车的按钮,未登录时点击跳转到登录页。
思路:创建一个vue指令(directive)能生成一个元素覆盖再购物车按钮上:
Vue.directive('auth', function(el){
const token = store.state.user.token
if (!token) { // 鉴权判断,建议使用用户信息,此处图个方便
el.style.position = 'relative'
const oDiv = document.createElement('div')
oDiv.style.position = 'absolute'
oDiv.style.top = 0
oDiv.style.bottom = 0
oDiv.style.left = 0
oDiv.style.right = 0
oDiv.style.zIndex = 9999
oDiv.style.opacity = 0
oDiv.addEventListener('click', function(){
router.push('/login')
})
el.appendChild(oDiv)
}
})
<button v-auth @click='addToCart'>加入购物车</button>
其他问题
鉴权失败(或token失效)
后端验证token失败,返回的response中带有{ err: -1 }。
处理逻辑如下:
function errFunc(response){
if (response.data.err===-1) { // 验证token失败
vueStore.commit('user/updateToken', null) // 清空vue store
localStorage.removeItem('token') // 清除localStorage中的token(如果有的话)
vueRouter.replace('/login') // 跳转登录页
}
}
将方法放入axios拦截器中
axiosInstance.interceptors.request.use(errFunc)
刷新页面
在app.vue创建之时:
- 读取sessionstorage中的数据存储在store中,此时用vuex.store的replaceState方法,替换store的根状态
- 在window.beforeunload事件方法中将store.state存储到sessionstorage中。
// app.vue
export default {
name: 'app',
created () {
// 在页面加载时读取sessionStorage
if (sessionStorage.getItem('store')) {
this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem('store'))))
}
// 在页面刷新时将store保存到sessionStorage里
window.addEventListener('beforeunload', () => {
sessionStorage.setItem('store', JSON.stringify(this.$store.state))
})
}
}
最后
本文只是简述,更详细的还是得看花裤衩大佬的手摸手,带你用 vue 撸后台 系列二(登录权限篇)