⌈本文是作者本人学习过程中的笔记总结,若文中有不正确或需要补充的地方,欢迎在评论区中留言⌋🤖
一、【实现思路】🚩
- 小程序端登录时,除了返回用户信息,还需返回两个 token 信息
- accessToken:用于验证用户身份
- refreshToken:用于刷新 accessToken
- 当请求返回状态码为401(即 accessToken 过期)时,使用 refreshToken 发起刷新请求
- 刷新成功会拿到新的 accessToken 和 refreshToken
- 然后使用新的 accessToken 将失败的请求重新发送
二、【流程图】🚩
图中为大致流程,为了看起来简洁直观,略去了与本文内容不相关的步骤
三、【后端代码】🚩
1. ⌈签发和验证 token⌋🍥
- 签发 accessToken 时,设置的过期时间是4个小时
- 签发 refreshToken 时,设置的过期时间是7天
- 自己在测试的时候,可以把时间改短一点,例如30s
- 正常实现的效果是:登录时间超过4个小时之后,再次发送需要身份验证的请求,会使用 refreshToken 去请求刷新 accessToken;如果距离上次登录已经超过了7天,则会提示重新登录
- 这样的话,实现了一定的安全性(因为 accessToken 每隔4个小时就会更新),同时又没有让用户频繁地重新登录
2. ⌈登录⌋🍥
- 拿到请求参数中的登录凭证(code),以及保存的 appId 和 appSecret
- 基于上述三个参数发送请求到微信官方指定的服务器地址,获取 openid
- openid 是小程序登录用户的唯一标识,每次登录时的登录凭证(code)会变,但是获取到的 openid 是不变的
- 根据 openid 在数据库中查找用户,如果没有查找到,说明本次登录是当前用户的首次登录,需要创建一个新用户,存入数据库中
- 然后根据用户 id 以及设置的签发密钥进行 accessToken 和 refreshToken 的签发
- 签发密钥可以是自己随意设置的一段字符串,两个 token 要设置各自对应的签发密钥
- 这个签发密钥,在进行 token 验证的时候会使用到
四、【前端代码】🚩
1. ⌈封装的登录方法⌋🍥
- 在创建微信小程序项目时,默认是在根目录下 app.js 的 onLaunch 生命周期函数中进行了登录
- 也就是说每次在小程序初始化的时候都会进行登录操作
- 作者这里是把登录操作单独提取出来了,这样可以在个人主页界面专门设置一个登录按钮
- 当本地存储的用户信息被清除,或者上面提到的 refereshToken 也过期的情况下,我们点击登录按钮进行登录操作
import { loginApi } from '@/api/v1/index'
const login = async () => {
try {
// 登录获取 code
const {code} = await wx.login()
// 调用后端接口,获取用户信息
const {user, accessToken, refreshToken} = await loginApi(code)
wx.setStorageSync('profile', user)
wx.setStorageSync('accessToken', `Bearer ${accessToken}`)
wx.setStorageSync('refreshToken', refreshToken)
} catch (error) {
wx.showToast({
title: '登录失败,请稍后重试',
icon: 'error',
duration: 2000
})
}
}
export default login
2. ⌈封装的请求方法⌋🍥
- 接收5个参数:url、method、params、needToken、header(点击展开)
- url: 请求地址,是部分地址(例如:/auth/login),后面处理时会将其与设置的 baseUrl(例如:http://localhost:4000/api/v1) 进行拼接
- method:请求方法,默认值为 'GET'
- params:请求参数,数据格式为 object,例如: {name: 'test'}
- needToken:是否需要需要携带 token(即是否需要身份验证),默认值为 false
- header:请求头信息,数据格式为 object(例如: {'Content-Type': 'application/json'}),默认值为 null
-
需要携带 token 的请求,先从本地存储中取出 accessToken 信息,然后将其赋值给 header 中的 Authorization 属性(注意:首字母要大写)。在上面的验证 token 代码中,会根据 req.headers.authorization.split(' ')[1] 获取到请求头中传递的 accessToken 信息
-
调用 wx.request 发送请求,在 success 回调函数中判断请求返回信息中的状态码,根据状态码的不同做对应的操作,这里只讨论401 token 过期的情况
- 当 token 过期时,从本地存储中获取到 refreshToken,然后调用对应后端接口刷新 token(点击展开)
- 在刷新请求发送前,需要先判断是否已经有刷新请求被发送且正在处理中(基于 isTokenRefreshing 标识)
- 如果有,则不必再重复发送刷新请求,但是需要把本次因为 401 token 过期而导致失败的请求存起来(放入 failedRequests 数组中),等待当前正在处理的 token 刷新请求完成后,使用新的 accessToken 重新发送本次请求
- 如果没有,则发送刷新请求,同时修改 isTokenRefreshing 标识的值为 true
-
等待刷新请求完成,将返回的新 accessToken 和 refreshToken 存储起来文章来源:https://www.toymoban.com/news/detail-810373.html
-
然后将 failedRequests 中因为等待 token 刷新而存储起来的失败请求,基于新的 accessToken 重新发送文章来源地址https://www.toymoban.com/news/detail-810373.html
- 最后将本次因为 401 token过期导致失败的请求,基于新的 accessToken 重新发送(点击展开)
- 本次操作正常进行 token 刷新请求,说明本次请求也是 token 过期了,而且因为 isTokenRefreshing 标识为 false, 没有将本次失败的请求存入 failedRequests 中
【源码】🚩
- 后端源码:github.com/Yu19980809/…
- 前端源码:github.com/Yu19980809/…
【说明】🚩
- 文中涉及到的代码都是作者本人的书写习惯与风格,若有不合理的地方,欢迎指出
- 如果本文对您有帮助,烦请动动小手点个赞,谢谢
到了这里,关于【微信小程序】 token 无感刷新的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!