Token是什么
-
token的意思是“令牌”,是服务端生成的一串字符串。
-
作为客户端进行请求的一个标识。当用户第一次登录后,服务器生成一个token并将此token返回给客户端。
-
以后客户端只需带上这个token前来请求数据即可,无需再次带上用户名和密码。
-
简单token的组成;uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token的前几位以哈希算法压缩成的一定长度的十六进制字符串。为防止token泄露)。
token操作
-
登录时把token存起来 ,请求时把token取过来放到请求头中,一次来验证身份,区分数据等操作。
-
其次token是前后端来验证的加密标识,所以他就会有时效性所以他就有主动处理和被动处理。
前言
在实际开发中,我们一般会把这些需要存的东西借助浏览器存,取,删。或者存到别的插件中,但是原理是一样的,我们为了简化开发一般会使用cookie和localStorage。小编这里使用的是cookie,在Vue工具文件utils封装方法暴露,引入使用。
localStorage和cookie区别
cookie使用
1.我们先在utils/auth.js 中封装Token 存 取 删 方法 顺便把getTokenTime(token时间也封装一下)后面token主动处理的时候要用到。
import Cookies from 'js-cookie'
const TokenKey = 'UT_token'
// 专门用来记录token开始时间的
const TimeKey = 'Token_time'
const TenantIdKey = 'TENANT_ID'
// 获取
export function getToken () {
return Cookies.get(TokenKey)
}
// 设置
export function setToken (token) {
// debugger
return Cookies.set(TokenKey, token)
}
// 删除
export function removeToken () {
return Cookies.remove(TokenKey)
}
// 获取token开始的时间
export function getTokenTime () {
return Cookies.get(TimeKey)
}
// 设置token开始的时间
export function setTokenTime () {
return Cookies.set(TimeKey, Date.now())
}
// 删除token开始的时间
export function removeTokenTime () {
return Cookies.remove(TimeKey)
}
export function getTenantId () {
return Cookies.get(TenantIdKey)
}
export function setTenantId (username) {
return Cookies.set(TenantIdKey, username)
}
export function removeTenantId () {
return Cookies.remove(TenantIdKey)
}
token过期 - 被动处理
-
token超时的错误码是401
-
当token过期,请求就会报错,那就会触发
响应拦截
里的错误拦截
,在错误拦截里
判断是不是token过期的状态码,如果是,就调用退出的方法(删token和userInfo),然后弹出错误提示,以及打回登录页。
流程图
在响应拦截中添加如下代码(具体的看我其他文章-拦截器使用)
// 响应拦截
service.interceptors.response.use(
res => {
return res;
},
async error => {
// token失效的被动处理
console.log(error)
if (error.response.data.code === 401) {
await store.dispatch('user/logout')
Message.warning('登录状态过期,请重新登录!')
router.push('/login')
} else {
return Promise.reject(error)
}
}
)
为什么需要主动处理
-
虽然token过期,我们可以利用响应拦截来知道token过期了,并且做出一定的处理
-
但是有一个场景,比如后端token是4小时失效,他失效之后我们只有发了请求响应之后才知道token已经失效
-
响应拦截在请求之后才会响应,那就意味着肯定要发一次请求(token已过期),并且还是一个无效请求。
-
比如有10000个用户就有10000个token都过期之后,就要发10000请求才能知道浪费资源,这个时候token的主动处理就可以解决这个问题。
示意图
token过期 - 主动处理
-
通过utils/auth.js 文件中getTokenTime(时间)存 取方法在vuex做登录的时候存(store/modules/user.js)在utils/request.js中取出来判断。
存token和时间
token和记录时间都是在点登陆的时候掉接口获取和记录时间存储到cookie,因为我们在vuex做的登录所以我们要在vuex进行存 取 删代码实现。
store/modules/user.js文件
import { login, getInfo } from '@/api/user'
import { getToken, setToken, setTokenTime } from '@/utils/auth'
import { Message } from 'element-ui'
import websocket from '@/utils/websocket'
const getDefaultState = () => {
return {
token: getToken(),
}
}
const state = getDefaultState()
// 方法
const mutations = {
// 登录
SET_TOKEN: (state, token) => {
state.token = token
setToken(token)
setTokenTime()
},
}
// 请求
const actions = {
// 登录
async login (ctx, data) {
let res = await login(data)
// console.log(res)
// 调用mutations里的方法存到state
ctx.commit('SET_TOKEN', res.data)
},
// 退出登录
logout (ctx) {
ctx.commit('SET_TOKEN', '')
Message.success('退出成功,请重新登录')
}
}
export default {
// 开启私密空间
namespaced: true,
state,
mutations,
actions
}
浏览器cookie存储
流程图
在请求拦截中添加如下代码(具体的看我其他文章-拦截器使用)
// 请求拦截
service.interceptors.request.use(
async config => {
// config就是本次发请求的信息
// 判断有没有token
if (store.state.user.token) {
// token失效的主动处理
// 获取一下记录token的时间
let start = getTokenTime()
// 获取一下当前时间
let now = Date.now()
// 算出时间差
let hour = (now - start) / 1000 / 3600
// 判断是否超过1小时
if (hour >= 1) {
// 代表token过期 登出方法
await store.dispatch('user/logout')
Message.error('token已过期,请重新登录')
router.push('/login')
// return代表不往下执行,所以这个请求不会发送
return
}
// 根据自己后端token格式 修改
// config.headers.Authorization = 'Bearer ' + getToken()
config.headers['Bearer'] = getToken()
// config.headers.tenantid = getTenantId ()
}
// 发送请求
return config
},
error => {
return Promise.reject(error)
}
)
注意:记得引入相关方法和组件(完整版-看我其他文章-拦截器使用)
import { login, getInfo } from '@/api/user'
import { getToken, setToken, setTokenTime } from '@/utils/auth'
import { Message } from 'element-ui'
总结:
经过这一趟流程下来相信你也对 Vue Token 原理 操作处理 有了初步的深刻印象,但在实际开发 中我 们遇到的情况肯定是不一样的,所以我们要理解它的原理,万变不离其宗。加油,打工人!
有什么不足的地方请大家指出谢谢 -- 風过无痕