怎么做教育培训网站,最新app推广,建设银行网站用户名更改,怎样用jsp做网站登录token刷新的方案 方案一#xff1a;后端返回过期时间#xff0c;前端判断token过期时间#xff0c;去调用刷新token的接口 缺点#xff1a;需要后端提供一个token过期时间的字段#xff1b;使用本地时间判断#xff0c;若本地时间被修改#xff0c;本地时间比服务…token刷新的方案 方案一后端返回过期时间前端判断token过期时间去调用刷新token的接口 缺点需要后端提供一个token过期时间的字段使用本地时间判断若本地时间被修改本地时间比服务器时间慢拦截会失败。 方案二写个定时器定时刷新token接口 缺点浪费资源消耗性能不建议采用 方案三在响应拦截器中拦截判断token返回过期后调用刷新token接口⭕推荐使用 token失效后接口返回401 有感刷新 清除token强制跳转回登录页有感知的重新登录拿到新token替换到本地体验不好 !
if (res.code 401 || res.code 493){EIMessage.warning(登录已失效,请重新登录 !)sessionstorage.clear()localstorage .removeitem(token)router.push({ path: /login })return
}
无感刷新 使用登录时保存的refresh_token调用另一个接口换回新的token值替换到本地再次完成本次未完成的请求用户无感知 具体步骤 1、首次登录的时候会获取到两个token 一个是平时请求接口正常使用的token过期时间短另一个是专门用于刷新的refresh_token过期时间一般比较长登陆时都存起来 localStorage.setItem(‘refresh_token’,xxx) localStorage.setItem(‘token’, xxx) 2、在响应拦截器中对401状态码引入刷新token的api方法调用 3、替换保存本地新的token 4、headers替换新的token 5、axios再次发起未完成的请求返回promise对象到最开始发起请求的页面 6、如果refresh_token也过期了那就判断是否过期过期了就清除localstorage跳转回登录页面
登陆时拿到的后端数据 存起来 refreshToken.js
import request from ./requestexport function refreshToken() {const resp request.get(/refresh_token, {headers: {token: ${refresh_token}},__isRefreshToken: true})// return resp.code 0 // 等于0表示刷新token成功
}export function isRefreshRequest(config) {return !!config.__isRefreshToken //两个取反变成boolean
}request.js
import axios from axios
import { refreshToken, isRefreshRequest } form ./refreshToken.js// 创建axios实例
const service axios.create({// baseURL: ,// 所有的请求地址前缀部分timeout: 25000, // 请求超时时间(毫秒)withCredentials: true// 异步请求携带cookie
})// 请求拦截器
service.interceptors.request.use((config: any) {...
}, error {...
})// 响应拦截器
service.interceptors.response.use((response: any) {let res response.dataif (res.code 401 !isRefreshRequest(res.config)){ // 如果没有权限且不是刷新token的请求// 刷新tokentry {const res await refreshToken()// 保存新的tokenlocalStorage.setItem(token, res.data.token)// 有新token后再重新请求response.config.headers.token localStorage.getItem(token) // 新tokenconst resp await service.request(response.config)return resp.data// return service(response.config)}catch {localStorage.clear() // 清除tokenrouter.replace(/login) // 跳转到登录页}}
}, error {...console.log(error, error)return Promise.reject(error)
})问题一如何防止多次刷新token
为了防止多次刷新token可以通过一个变量isRefreshing 去控制是否在刷新token的状态
request.js
import axios from axios
import { refreshToken, isRefreshRequest } form ./refreshToken.js// 创建axios实例
const service axios.create({// baseURL: ,// 所有的请求地址前缀部分timeout: 25000, // 请求超时时间(毫秒)withCredentials: true// 异步请求携带cookie
})// 请求拦截器
service.interceptors.request.use((config: any) {...
}, error {...
})// 响应拦截器
service.interceptors.response.use((response: any) {let res response.datalet isRefreshing falseif (res.code 401 ! isRefreshRequest(res.config)){ // 如果没有权限且不是刷新token的请求if (!isRefreshing) {isRefreshing true// 刷新tokentry {const res await refreshToken()// 保存新的tokenlocalStorage.setItem(token, res.data.token)// 有新token后再重新请求response.config.headers.token localStorage.getItem(token) // 新tokenconst resp await service.request(response.config)return resp.data// return service(response.config)}catch {localStorage.clear() // 清除tokenrouter.replace(/login) // 跳转到登录页}isRefreshing false}}
}, error {...console.log(error, error)return Promise.reject(error)
})问题二同时发起两个或者两个以上的请求时怎么刷新token
当第二个过期的请求进来token正在刷新我们先将这个请求存到一个数组队列中想办法让这个请求处于等待中一直等到刷新token后再逐个重试清空请求队列。 那么如何做到让这个请求处于等待中呢 为了解决这个问题我们得借助Promise。将请求存进队列中后同时返回一个Promise让这个Promise一直处于Pending状态即不调用resolve此时这个请求就会一直等啊等只要我们不执行resolve这个请求就会一直在等待。当刷新请求的接口返回来后我们再调用resolve逐个重试。
request.js
import axios from axios
import { refreshToken, isRefreshRequest } form ./refreshToken.js// 创建axios实例
const service axios.create({// baseURL: ,// 所有的请求地址前缀部分timeout: 25000, // 请求超时时间(毫秒)withCredentials: true// 异步请求携带cookie
})// 请求拦截器
service.interceptors.request.use((config: any) {...
}, error {...
})// 响应拦截器
service.interceptors.response.use((response: any) {let res response.datalet isRefreshing falselet requests [] // 请求队列if (res.code 401 isRefreshRequest(res.config)){ // 如果没有权限且不是刷新token的请求if (!isRefreshing) {isRefreshing true// 刷新tokentry {const res await refreshToken()// 保存新的tokenlocalStorage.setItem(token, res.data.token)// 有新token后再重新请求response.config.headers.token localStorage.getItem(token) // 新token// token 刷新后将数组的方法重新执行requests.forEach((cb) cb(token))requests [] // 重新请求完清空const resp await service.request(response.config)return resp.data// return service(response.config)}catch {localStorage.clear() // 清除tokenrouter.replace(/login) // 跳转到登录页}isRefreshing false} else {// 返回未执行 resolve 的 Promisereturn new Promise(resolve {// 用函数形式将 resolve 存入等待刷新后再执行request.push(token {response.config.headers.token ${token}resolve(service(response.config))})})}}
}, error {...console.log(error, error)return Promise.reject(error)
})