解析如何在vue前端处理token
[toc]
token(令牌)是用户登录后获取的一种凭证。
那么,用户登录后访问其他API都需要携带token,才可以成功请求;所以如果没有携带,便不可以请求成功。
好处:如果不使用token,可能请求时都需要去验证用户名和密码,那么这就造成对服务器算力的浪费,使用token,便可以减少服务器的压力,减少频繁的查询数据库。
token具有时效性,可能有效期是几分钟,或者几天。
token生成机制一般是通过加密算法和盐把类似(用户名 + 时间戳 + 盐)生成串
而后端生成token后,会把它存在Redis(缓存)中。
使用token这项技术,后端可以做单点登录(只允许一个账号同时登录1次,不允许一个账号同时登录多次,是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分)
所以我们依然以《电商管理系统》这个项目为基础,分析
1、如何在登录之后存储token(登录的post请求,会返回一个token)
2、如何在访问其他API时,携带token(如何配置)
1、如何在登录之后存储token
需要在客户端存储token,
(1)可以存储在cookie中,
cookie指的就是浏览器里面能永久存储数据的一种数据存储功能。cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。
由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。
(2)可以存储在sessionStorage或者是localStorage
cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递,
localStorage 和 sessionStorage 属性允许在浏览器中存储 key/value 对的数据。
localStorage 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去删除。
localStorage 属性是只读的。
如果你只想将数据保存在当前会话中,可以使用sessionStorage 属性, 该数据对象临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据。
在js中,使用window对象调用sessionStorage和localStorage
Window 对象表示浏览器中打开的窗口。
此处补充一些window对象的内容:
(1)Window 对象的属性
closed 返回窗口是否已被关闭。 localStorage 在浏览器中存储 key/value 对。没有过期时间。 parent 返回父窗口 sessionStorage 在浏览器中存储 key/value 对。 在关闭窗口或标签页之后将会删除这些数据。 (2)Window 对象的方法
alert() 显示带有一段消息和一个确认按钮的警告框 clearTimeout() 取消由 setTimeout() 方法设置的 timeout close() 关闭浏览器窗口 print() 打印当前窗口的内容。 setTimeout() 在指定的毫秒数后调用函数或计算表达式。
在登录页面中,在发起请求登录时,存储token代码如下:
login() {
this.$refs.loginFormRef.validate(async valid => {
// console.log(valid);
if (!valid) return;
const { data: res } = await this.$axios.post('login', this.loginForm);
console.log(res);
if (res.meta.status != 200) return this.$message.error('登录失败!');
this.$message.success('登录成功!');
// 1.将登录成功后的token,保存到客户端的sessionStorage中
// 1.1项目中除了登录之外的其他API接口,必须在登录之后才能访问
// 1.2token只应在当前网站打开期间生效,所以将token保存在sessionStorage中
window.sessionStorage.setItem('token', res.data.token);
// 2.通过编程式导航跳转到后台主页,路由地址是 /home
this.$router.push('/home');
});
}
可以通过浏览器在Application查看如下:
下面考虑第二个问题,
2、如何在访问其他API时,携带token(如何配置)
第一步:如果我们没有登录,直接通过URL,访问除了登录页面以外的页面,是不可以访问的,可以让它跳转到登录页面。这一步,我们利用路由导航守卫来完成
为router路由对象,添加beforeEach导航守卫。如果用户访问的是登录页,直接放行;如果访问是其他页面,则从sessionStorage取token,看是否为空,如果为空,则跳转到登录页。
router.beforeEach((to, from, next) => {
//to将要访问的路径
//from代表从哪个路径跳转而来
//next是一个函数,表示放行
//next() 放行 next('/login')强制跳转
if (to.path === '/login') return next();
//获取token
const tokenStr = window.sessionStorage.getItem('token');
if (!tokenStr) return next('/login');
next();
});
注意next函数
next() 放行
next(‘/login’)跳转到指定页面
第二步:通过axios请求拦截器添加token
在接口文档中已经说明,需要授权的 API ,必须在请求头中使用 Authorization 字段提供 token 令牌 。
在导入axios包后,
做一个请求拦截器,类似于对请求进行预处理,我们在axios的一个use方法中,调用了一个箭头函数,这个箭头函数会将对请求头的Authorization字段填入token值
config即是一个请求对象
代码是在main.js入口文件中,配置如下:
axios.interceptors.request.use(config => {
console.log(config);
config.headers.Authorization = window.sessionStorage.getItem('token');
// 在最后必须return config
return config;
});
例如登录的config在console中打印长这个样子:
好了,那我们现在去检查一下别的接口在请求时,是否在请求头中携带了Authorization,在浏览器中选择Network
选择menus这个请求,发现它在请求头中的Authorization带了token,成功。
3、退出登录、销毁token、并跳转登录页
那么当我们退出登录时,其实就是销毁了获得的token,那么后续的请求必须生成新的token;
并且退出后跳转到登录页面
点击“退出”按钮,触发logout方法,代码如下:
logout() {
window.sessionStorage.clear();
this.$router.push('/login');
},