登录与退出功能-保存token和设置token过期时间过期重新到登录页面
Vue项目登录与退出功能-保存token和页面权限控制,设置token过期时间过期重新到登录页面,本地保存有token就直接不用输入账号密码跳转到首页
做vue后台管理系统的项目的过程中有个登录退出的业务逻辑:
- (1)发起登录请求之前做个对账号密码表单的合法性进行验证规则
- (2)登录的时候发起请求获取token
- (3)将token保存到本地
- (4)路由导航守卫:设置token的过期时间,如果过期了就重新导登录页面,如果用户在token还没有过期的时候打开了登录页面就直接跳转到首页
其实我们在登录成功之后,需要完成以下内容,来保持登录效果以及跳转登录首页:
1、将登录成功后的token,保存到客户端的sessionStorage中
(1) 项目中除了登录login组件接口,其他的组件页面必须在登录后才能访问
(2) token只应在当前网站打开期间生效,所以将token保存在sessionStotage中。
2、通过编程式导航this.$router.push('/home') 跳转到后台主页,路由地址是/home。
上面是对表单输入内容的合法性的验证规则。
下一步是主题内容....
login.vue
code
login() {
this.$refs.loginFormRef.validate(async valid => {
if (!valid) return
const { data: res } = await this.$http.post('login', this.loginForm) /* 加await返回的是数据 不加返回promise 而返回的数据里面只有data才是api返回的数据 其他的都是axios的 解构并重命名即data重命名为res */
if (res.meta.status !== 200) return this.$message.error('登录失败!')
this.$message.success('登录成功')
// 登录成功后:
// 1. 将登录成功之后的 token,保存到客户端的 sessionStorage 中 之后的网络请求中要拿这个token放入请求头中
// 1.1 项目中除了登录之外的其他API接口,必须在登录之后才能访问 token就是登录令牌
// 1.2 token 只应在当前网站打开期间生效,所以将 token 保存在 sessionStorage 中(不是localstorage)
window.sessionStorage.setItem('token',res.data.token)
this.$router.push('/home')
// 2. 通过编程式导航跳转到后台主页,路由地址是 /home 但是如果没有拿到token而直接输入地址也不应该跳转 此时要用导航守卫 如果要跳转的是登录页面则直接放行 如果跳转的是其他页面则要判断是否携带token 导航守卫写在router.js里面
// this.$router.push('/home')
})
},
因为登录成功之后,需要跳转到后台首页,所以使用$router的push进行路由跳转 ,路由地址是“/home”
由于我们的Home页面是需要在登录成功之后才可以进行访问的,所以登录之前我们要控制用户无法访问该页面,如何做呢?
- 除了login请求接口,其他都需要授权,才能正常请求数据,所以axios请求拦截器添加token,保证获取数据的权限
里面有 headers 属性,手动保存在session本地,把这个令牌给token保存下来
必须是 return config
main.js 代码:
code
// 添加请求拦截器
// 拦截器的第一部分,第二部分在router index.js里面
axios.interceptors.request.use(function(config) {
// 在发送请求之前做些什么
// 判断是否存在token,如果存在将每个页面header添加token
if (window.localStorage.getItem("token")) {
config.headers.common['Access-Token'] = window.localStorage.getItem("token");
}
return config
})
我们要“路由导航守卫”来控制访问权限。如果用户没有登录,但是直接通过URL访问特定页面,需要重新导航到登录页面。router的beforeEach方法就是“路由导航守卫”,我们可以遍历router的所有路由地址,并可以设置跳转的动作。思路很简单,如果当前访问页面是登录页面,就正常跳转,如果不是,就检测是不是登录状态(token是否为空),如果不是,就跳转到登录页面,如果是就正常跳转。
我们在路由规则文件/router/index.js下,编写“挂载路由导航守卫”的逻辑:
router/index.js
code
// 挂载路由导航守卫
router.beforeEach((to, from, next) => {
// to 将要访问的路径
// from 代表从哪个路径跳转而来
// next 是一个函数,表示放行
// next() 放行 next('/login') 强制跳转
if (to.path === '/login') return next()
// 其他页面则要有token才能放行 之后的网络请求中要拿这个token放入请求头中
const tokenStr = window.sessionStorage.getItem('token')
if (!tokenStr) return next('/login') /* 没有用else if */
next()
})
export default router /* 因为要挂载导航守卫 所以不能实时导出 */
其实上面的是比较常见的方法。还有一种是最完整的写法(token设置期限,token过期让客户重新登录等功能):
- // 添加请求拦截器 // 拦截器的第二部分,第一部分在main.js里面
- // 获取存储token的开始时间
- // 后台给出的token有效时间,一个星期 单位 是秒
- // 我们自己定义6天过期,让用户重新登录一下, 用户总不可能在一个页面挂机一天吧
- // 当前时间 // 如果大于说明是token过期了
- // 如果token过期了
- // 如果token没有过期,又是选择了登录页面就直接重定向到首页,不需要重新输入账户密码
code
// 别忘了导入对应的依赖库----
//导入element提示语的组件
// 添加请求拦截器
// 拦截器的第二部分,第一部分在main.js里面
router.beforeEach((to, from, next) => {
// 获取存储localStorage的token
let token = window.localStorage.getItem('token')
// 获取存储token的开始时间
const tokenStartTime = window.localStorage.getItem('tokenStartTime')
// 后台给出的token有效时间,一个星期 单位 是秒
// 我们自己定义6天过期,让用户重新登录一下, 用户总不可能在一个页面挂机一天吧
const timeOver = 6 * 24 * 3600 * 1000
// 当前时间
let date = new Date().getTime()
// 如果大于说明是token过期了
if(date - tokenStartTime > timeOver) {
token = null
}
// 如果token过期了
if (!token) {
if (to.path == '/login') return next()
// 注意要import element的Message组件
Message.error("登录状态过期,请重新登录")
return next('/login')
// 如果token没有过期,又是选择了登录页面就直接重定向到首页,不需要重新输入账户密码
} else if (to.path == '/login') {
return next('/home')
}
next()
})
export default router