网站文章不收录怎么做,怎样手机做网站教程,凡科网站官网登录入口,做网站要多无感刷新
无感刷新Token技术是一种用于实现持久登录体验的关键技术#xff0c;它通过在用户登录后自动刷新Token#xff0c;以延长用户的登录状态#xff0c;避免频繁要求用户重新登录。
实现
使用access_token#xff08;短效token#xff09;和refresh_token#xf…无感刷新
无感刷新Token技术是一种用于实现持久登录体验的关键技术它通过在用户登录后自动刷新Token以延长用户的登录状态避免频繁要求用户重新登录。
实现
使用access_token短效token和refresh_token长效token当请求拦截判断属于access_token过期时使用refresh_token获取一组新的token并且将所有无效请求入队列等拿到有效token时依次出队列重新请求。
后端
使用nestjs写了几个测试用的接口
controller.ts
import { Body, Query, Controller,Request, Get, Post, BadRequestException, Inject, Req, UnauthorizedException } from nestjs/common;
import { AppService } from ./app.service;
import { UserDto } from ./dto/user.dto;
import { JwtService } from nestjs/jwt
const users [{ username:admin, password:admin },{ username:zhangsan, password:123 },
]Controller()
export class AppController {constructor(private readonly appService: AppService) {}Inject(JwtService)private jwtService:JwtService;Get()getHello(): string {return this.appService.getHello();}Post(login)login(Body() userDto : UserDto){const user users.find(item item.username userDto.username);if(!user) {throw new BadRequestException(用户不存在);}if(user.password ! userDto.password) {throw new BadRequestException(密码错误);}const accessToken this.jwtService.sign({username:user.username,}, {expiresIn: 0.001h})const refreshToken this.jwtService.sign({username:user.username,}, {expiresIn: 7d})return {userInfo: {username: user.username,},accessToken: accessToken,refreshToken: refreshToken};}Get(aaa)aaa(Req() req: Request){const authorization req.headers[authorization];if(!authorization){throw new UnauthorizedException(用户未登录)}try {const token authorization;const data this.jwtService.verify(token);console.log(data);return aaa} catch (error) {throw new UnauthorizedException(token失效请重新登录)}}Get(bbb)bbb(Req() req: Request){const authorization req.headers[authorization];if(!authorization){throw new UnauthorizedException(用户未登录)}try {const token authorization;const data this.jwtService.verify(token);console.log(data);return bbb} catch (error) {throw new UnauthorizedException(token失效请重新登录)}}Get(refresh)refresh(Query(token) token: string) {try{const data this.jwtService.verify(token);const user users.find(item item.username data.username);const accessToken this.jwtService.sign({username: user.username,}, {expiresIn: 0.001h});const refreshToken this.jwtService.sign({username: user.username}, {expiresIn: 7d})return {accessToken,refreshToken};} catch(e) {throw new UnauthorizedException(token 失效请重新登录);}}}其中login生成 access_token 和 refresh_token
前端请求封装
import axios from axios;
import { userStore } from /store/user.js
const store userStore();
class RequestQueue {constructor() {this.queue [];this.isRefresh false;}// 入队enqueue(value) {return this.queue.push(value);}// 出队dequeue() {return this.queue.shift();}// 取队头元素peek() {return this.queue[0];}// 判断队列是否为空isEmpty() {return this.queue.length 0;}// 取队列有多少个元素size() {return this.queue.length;}// 清空队列clear() {this.queue [];}setIsRefresh(isRefresh){return this.isRefresh isRefresh}
}
//1. 创建axios对象
const service axios.create({baseURL: import.meta.env.VITE_APP_BASE_API,// 超时timeout: 10000});
//2. 请求拦截器
service.interceptors.request.use(config {console.log(store拦截信息,store)if(store.accessToken){config.headers.Authorization store.accessToken;}return config;
}, error {Promise.reject(error);
});let requests new RequestQueue; // 请求队列
//3. 响应拦截器
service.interceptors.response.use(response {//判断code码return response.data;
},error {if(error.response.status 401){// token过期处理// 请求入队requests.enqueue(error.response.config);if(!requests.isRefresh){requests.setIsRefresh(true)store.doRefreshToken().then(res{while(!requests.isEmpty()){let config requests.dequeue()config.Authorization store.accessTokenservice.request(config)}requests.setIsRefresh(false)});}} else {// token请求没有过期return new Promise((resolve,reject){reject(error)});}
});
export default service;