返回顶部
首页 > 资讯 > 前端开发 > JavaScript >Vue3+Vite使用双token实现无感刷新
  • 599
分享到

Vue3+Vite使用双token实现无感刷新

Vue3无感刷新Vue3双token无感刷新 2023-05-17 14:05:03 599人浏览 安东尼
摘要

目录前言一、token 登录鉴权二、何为双 token双 token 验证流程注意事项三、服务端代码1. 搭建koa2服务器2. 双token3. 路由4. 应用中间件四、前端代码1

前言

近期写的一个项目使用双token实现无感刷新。最后做了一些总结,本文详细介绍了实现流程,前后端详细代码。前端使用了Vue3+Vite,主要是axios封装,服务端使用了koa2做了一个简单的服务器模拟。

一、token 登录鉴权

JwtJSON WEB Token。是一种认证协议,一般用来校验请求的身份信息和身份权限。 由三部分组成:Header、Hayload、Signature

header:也就是头部信息,是描述这个 token 的基本信息,json 格式

{
  "alg": "HS256", // 表示签名的算法,默认是 HMac SHA256(写成 HS256)
  "type": "JWT" // 表示Token的类型,JWT 令牌统一写为JWT
}

payload:载荷,也是一个 JSON 对象,用来存放实际需要传递的数据。不建议存放敏感信息,比如密码。

{
  "iss": "a.com", // 签发人
  "exp": "1d", // expiration time 过期时间
  "sub": "test", // 主题
  "aud": "", // 受众
  "nbf": "", // Not Before 生效时间
  "iat": "", // Issued At 签发时间
  "jti": "", // JWT ID 编号
  // 可以定义私有字段
  "name": "",
  "admin": ""
}

Signature 签名 是对前两部分的签名,防止数据被篡改。 需要指定一个密钥。这个密钥只有服务器才知道,不能泄露。使用 Header 里面指定的签名算法,按照公式产生签名。

算出签名后,把 Header、Payload、Signature 三个部分拼成的一个字符串,每个部分之间用 . 分隔。这样就生成了一个 token

二、何为双 token

  • accessToken:用户获取数据权限
  • refreshToken:用来获取新的accessToken

双 token 验证机制,其中 accessToken 过期时间较短,refreshToken 过期时间较长。当 accessToken 过期后,使用 refreshToken 去请求新的 token。

双 token 验证流程

  • 用户登录向服务端发送账号密码,登录失败返回客户端重新登录。登录成功服务端生成 accessToken 和 refreshToken,返回生成的 token 给客户端。
  • 在请求拦截器中,请求头中携带 accessToken 请求数据,服务端验证 accessToken 是否过期。token 有效继续请求数据,token 失效返回失效信息到客户端。
  • 客户端收到服务端发送的请求信息,在二次封装的 axios 的响应拦截器中判断是否有 accessToken 失效的信息,没有返回响应的数据。有失效的信息,就携带 refreshToken 请求新的 accessToken。
  • 服务端验证 refreshToken 是否有效。有效,重新生成 token, 返回新的 token 和提示信息到客户端,无效,返回无效信息给客户端。
  • 客户端响应拦截器判断响应信息是否有 refreshToken 有效无效。无效,退出当前登录。有效,重新存储新的 token,继续请求上一次请求的数据。

注意事项

  • 短token失效,服务端拒绝请求,返回token失效信息,前端请求到新的短token如何再次请求数据,达到无感刷新的效果。
  • 服务端白名单,成功登录前是还没有请求到token的,那么如果服务端拦截请求,就无法登录。定制白名单,让登录无需进行token验证。

三、服务端代码

1. 搭建koa2服务器

全局安装koa脚手架

npm install koa-generator -g

创建服务端 直接koa2+项目名

koa2 server

cd server 进入到项目安装jwt

npm i jsonwebtoken

为了方便直接在服务端使用koa-cors 跨域

npm i koa-cors

在app.js中引入应用cors

const cors=require('koa-cors')
...
app.use(cors())

2. 双token

新建utils/token.js

const jwt=require('jsonwebtoken')

const secret='2023F_Ycb/wp_sd'  // 密钥

// 本次是为了测试,所以设置时间 短token5秒 长token15秒
const accessTokenTime=5  
const refreshTokenTime=15 

// 生成accessToken
const setAccessToken=(payload={})=>{  // payload 携带用户信息
    return jwt.sign(payload,secret,{expireIn:accessTokenTime})
}
//生成refreshToken
const setRefreshToken=(payload={})=>{
    return jwt.sign(payload,secret,{expireIn:refreshTokenTime})
}

module.exports={
    secret,
    setAccessToken,
    setRefreshToken
}

3. 路由

直接使用脚手架创建的项目已经在app.js使用了路由中间件 在router/index.js 创建接口

const router = require('koa-router')()
const jwt = require('jsonwebtoken')
const { getAccesstoken, getRefreshtoken, secret }=require('../utils/token')


router.get('/login',()=>{
    let code,msg,data=null
    code=2000
    msg='登录成功,获取到token'
    data={
        accessToken:getAccessToken(),
        refreshToken:getReferToken()
    }
    ctx.body={
        code,
        msg,
        data
    }
})


router.get('/getTestData',(ctx)=>{
    let code,msg,data=null
    code=2000
    msg='获取数据成功'
    ctx.body={
        code,
        msg,
        data
    }
})


router.get('/refresh',(ctx)=>{
    let code,msg,data=null
    //获取请求头中携带的长token
    let r_tk=ctx.request.headers['pass']
    //解析token 参数 token 密钥 回调函数返回信息
    jwt.verify(r_tk,secret,(error)=>{
        if(error){
            code=4006,
            msg='长token无效,请重新登录'
        } else{
            code=2000,
            msg='长token有效,返回新的token',
            data={
                accessToken:getAccessToken(),
                refreshToken:getReferToken()
            }
        }
    })
})

4. 应用中间件

utils/auth.js

const { secret } = require('./token')
const jwt = require('jsonwebtoken')


const whiteList=['/login','/refresh']
const isWhiteList=(url,whiteList)=>{
        return whiteList.find(item => item === url) ? true : false
}


const cuth = async (ctx,next)=>{
    let code, msg, data = null
    let url = ctx.path
    if(isWhiteList(url,whiteList)){
        // 执行下一步
        return await next()
    } else {
        // 获取请求头携带的短token
        const a_tk=ctx.request.headers['authorization']
        if(!a_tk){
            code=4003
            msg='accessToken无效,无权限'
            ctx.body={
                code,
                msg,
                data
            }
        } else{
            // 解析token
            await jwt.verify(a_tk,secret.(error)=>{
                if(error)=>{
                      code=4003
                      msg='accessToken无效,无权限'
                      ctx.body={
                          code,
                          msg,
                          datta
                      }
                } else {
                    // token有效
                    return await next()
                }
            })
        }
    }
}
module.exports=auth

在app.js中引入应用中间件

const auth=requier(./utils/auth)
···
app.use(auth)

其实如果只是做一个简单的双token验证,很多中间件是没必要的,比如解析静态资源。不过为了节省时间,方便就直接使用了koa2脚手架。

最终目录结构:

四、前端代码

1. Vue3+Vite框架

前端使用了Vue3+Vite的框架,看个人使用习惯。

npm init vite@latest client_side

安装axios

npm i axios

2. 定义使用到的常量

config/constants.js

export const ACCESS_TOKEN = 'a_tk' // 短token字段
export const REFRESH_TOKEN = 'r_tk' // 短token字段
export const AUTH = 'Authorization'  // header头部 携带短token
export const PASS = 'pass' // header头部 携带长token

3. 存储、调用过期请求

关键点:把携带过期token的请求,利用Promise存在数组中,保持pending状态,也就是不调用resolve()。当获取到新的token,再重新请求。 utils/refresh.js

export {REFRESH_TOKEN,PASS} from '../config/constants.js'
import { getRefreshToken, removeRefreshToken, setAccessToken, setRefreshToken} from '../config/storage'

let subsequent=[]
let flag=false // 设置开关,保证一次只能请求一次短token,防止客户多此操作,多次请求


export const addRequest = (request) => {
    subscribes.push(request)
}


export const retryRequest = () => {
    console.log('重新请求上次中断的数据');
    subscribes.forEach(request => request())
    subscribes = []
}


export const refreshToken=()=>{
    if(!flag){
        flag = true;
        let r_tk = getRefershToken() // 获取长token
        if(r_tk){
            server.get('/refresh',Object.assign({},{
                headers:{[PASS]=r_tk}
            })).then((res)=>{
                //长token失效,退出登录
                if(res.code===4006){
                    flag = false
                    removeRefershToken(REFRESH_TOKEN)
                } else if(res.code===2000){
                    // 存储新的token
                    setAccessToken(res.data.accessToken)
                    setRefreshToken(res.data.refreshToken)
                    flag = false
                    // 重新请求数据
                    retryRequest()
                }
            })
        }
    }
}

4. 封装axios

utlis/server.js

import axios from "axios";
import * as storage from "../config/storage"
import * as constants from '../config/constants'
import { addRequest, refreshToken } from "./refresh";

const server = axios.create({
    baseURL: 'Http://localhost:3004', // 你的服务器
    timeout: 1000 * 10,
    headers: {
        "Content-type": "application/json"
    }
})


server.interceptors.request.use(config => {
    // 获取短token,携带到请求头,服务端校验
    let aToken = storage.getAccessToken(constants.ACCESS_TOKEN)
    config.headers[constants.AUTH] = aToken
    return config
})


server.interceptors.response.use(
    async response => {
        // 获取到配置和后端响应的数据
        let { config, data } = response
        console.log('响应提示信息:', data.msg);
        return new Promise((resolve, reject) => {
            // 短token失效
            if (data.code === 4003) {
                // 移除失效的短token
                storage.removeAccessToken(constants.ACCESS_TOKEN)
                // 把过期请求存储起来,用于请求到新的短token,再次请求,达到无感刷新
                addRequest(() => resolve(server(config)))
                // 携带长token去请求新的token
                refreshToken()
            } else {
                // 有效返回相应的数据
                resolve(data)
            }

        })

    },
    error => {
        return Promise.reject(error)
    }
)

5. 复用封装

import * as constants from "./constants"

// 存储短token
export const setAccessToken = (token) => localStorage.setItem(constanst.ACCESS_TOKEN, token)
// 存储长token
export const setRefershToken = (token) => localStorage.setItem(constants.REFRESH_TOKEN, token)
// 获取短token
export const getAccessToken = () => localStorage.getItem(constants.ACCESS_TOKEN)
// 获取长token
export const getRefershToken = () => localStorage.getItem(constants.REFRESH_TOKEN)
// 删除短token
export const removeAccessToken = () => localStorage.removeItem(constants.ACCESS_TOKEN)
// 删除长token
export const removeRefershToken = () => localStorage.removeItem(constants.REFRESH_TOKEN)

6. 接口封装

apis/index.js

import server from "../utils/server";

export const login = () => {
    return server({
        url: '/login',
        method: 'get'
    })
}

export const getData = () => {
    return server({
        url: '/getList',
        method: 'get'
    })
}

项目运行

最后的最后,运行项目,查看效果 后端设置的短token5秒,长token10秒。登录请求到token后,请求数据可以正常请求,五秒后再次请求,短token失效,这时长token有效,请求到新的token,refresh接口只调用了一次。长token也过期后,就需要重新登录啦。

写在最后

这就是一整套的前后端使用双token机制实现无感刷新。token能做到的还有很多,比如权限管理、同一账号异地登录。本文只是浅显的应用了一下。

到此这篇关于Vue3+Vite使用双token实现无感刷新的文章就介绍到这了,更多相关Vue3 无感刷新内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Vue3+Vite使用双token实现无感刷新

本文链接: https://lsjlt.com/news/211216.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Vue3+Vite使用双token实现无感刷新
    目录前言一、token 登录鉴权二、何为双 token双 token 验证流程注意事项三、服务端代码1. 搭建koa2服务器2. 双token3. 路由4. 应用中间件四、前端代码1...
    99+
    2023-05-17
    Vue3 无感刷新 Vue3 双token无感刷新
  • 如何实现无感刷新token
    目录1、需求方法一方法二方法三2、实现3、问题解决问题一:如何防止多次刷新token问题二:同时发起两个或者两个以上的请求时,其他接口怎么解决前言: 最近在做需求的时候,涉及到登录t...
    99+
    2024-04-02
  • vue3+ts+axios+pinia实现无感刷新方式
    目录vue3+ts+axios+pinia实现无感刷新vue3无痛刷新(无感刷新)实现过程总结vue3+ts+axios+pinia实现无感刷新 1.先在项目中下载aiXos和pin...
    99+
    2023-05-16
    vue3 ts axios pinia vue3无感刷新 vue3刷新
  • 详细聊聊前端如何实现token无感刷新(refresh_token)
    目录关于无感刷新的理解: 下面是关于使用vuex来实现的写法axios工具函数(请求拦截器与响应拦截器)总结关于无感刷新的理解:  实现token无感刷新对于前端...
    99+
    2022-11-13
    前端无感知刷新token 前端自动刷新token 前端怎么刷新token
  • js无痛刷新Token的实现
    这个需求场景很常见,几乎很多项目都会用上,之前项目也实现过,最近刚好有个项目要实现,重新梳理一番。 需求 对于需要前端实现无痛刷新Token,无非就两种: 请求前判断Token是否过...
    99+
    2024-04-02
  • React如何使用refresh_token实现无感刷新页面
    目录步骤如下:具体实现步骤如下: 1-token过期根据refresh_token获取新的token 重新获取数据 2-创建一个新的axios实例 【使用request防止再次进入请...
    99+
    2024-04-02
  • React怎么使用refresh_token实现无感刷新页面
    这篇文章主要介绍了React怎么使用refresh_token实现无感刷新页面的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇React怎么使用refresh_token实现无感刷新页面文章都会有所收获,下面我们...
    99+
    2023-06-30
  • 使用javascript怎么实现页面无刷新更新数据
    这篇文章给大家介绍使用javascript怎么实现页面无刷新更新数据,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。 首先在服务器上建立一个CheckUser.asp文件,用来检测用户是否存在,根据用户是否存在...
    99+
    2023-06-10
  • 使用AJAX怎么实现无刷新分页功能
    使用AJAX怎么实现无刷新分页功能,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。  首先讲一下原理:分页有两个要点:1.有多少页,2.每页有多...
    99+
    2024-04-02
  • 使用Ajax怎么实现一个无刷新分页
    本篇文章为大家展示了使用Ajax怎么实现一个无刷新分页,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。<!doctype html><html lang=&quo...
    99+
    2023-06-08
  • 如何使用AJAX实现无刷新数据分页
    这篇文章将为大家详细讲解有关如何使用AJAX实现无刷新数据分页,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、实现过程注意:一下的内容都是在服务器内使用的。首先要在服务器的路径下建立几个文件,比如,pa...
    99+
    2023-06-08
  • 使用Vite搭建vue3+TS项目的实现步骤
    目录vite简介初始化项目修改vite.config.ts安装ts依赖和ESLint安装Axios配置跨域安装Lessvite简介 vite 是一个基于 Vue3 单文件组件的非打包...
    99+
    2023-01-11
    Vite搭建vue3+TS项目
  • jQ中如何使用ajax实现用户无刷新登录
    这篇文章给大家分享的是有关jQ中如何使用ajax实现用户无刷新登录的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。ajax俗称无刷新登录或局部刷新登录,这样可以提高用户体验了,文章...
    99+
    2024-04-02
  • 使用ajax怎么实现无刷新验证注册信息
    这篇文章将为大家详细讲解有关使用ajax怎么实现无刷新验证注册信息,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一.把注册的html页面做好(html+cs...
    99+
    2024-04-02
  • RecyclerView使用payload实现局部刷新
    本文实例为大家分享了RecyclerView使用payload实现局部刷新的具体代码,供大家参考,具体内容如下 列表局部刷新: 01.notifyDataSetChanged() 刷...
    99+
    2024-04-02
  • php中怎么利用ajax实现无刷新分页
    本篇文章为大家展示了php中怎么利用ajax实现无刷新分页,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。<php Header("Cont...
    99+
    2024-04-02
  • 怎么用PHP+jPaginate插件实现无刷新分页
    本篇内容主要讲解“怎么用PHP+jPaginate插件实现无刷新分页”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用PHP+jPaginate插件实现无刷新...
    99+
    2024-04-02
  • 怎么用ASP+Ajax实现无刷新评论功能
    本篇内容介绍了“怎么用ASP+Ajax实现无刷新评论功能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!&l...
    99+
    2024-04-02
  • 怎么使用Ajax实现异步刷新
    小编给大家分享一下怎么使用Ajax实现异步刷新,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!所谓的异步刷新,就是不刷新整个网页进行更新数据。只有通过js才能实现A...
    99+
    2023-06-08
  • 怎么使用Yii整合的pjax实现无刷新加载页面
    本篇内容主要讲解“怎么使用Yii整合的pjax实现无刷新加载页面”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Yii整合的pjax实现无刷新加载页面”吧...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作