外观
微信小程序登录鉴权实践
小程序没有传统 Web 的 Cookie/Session 环境,登录态需要自己设计。本文介绍我们在商城类小程序中稳定运行的登录鉴权方案。
登录流程
整体流程如下:
- 小程序端调用
wx.login()获取临时登录凭证code - 将
code提交给后端/api/v1/auth/login - 后端调用微信
code2Session接口,用appid + secret + code换取openid、session_key - 后端根据
openid查找或创建用户,签发自定义登录态token返回 - 小程序端将
token存入本地缓存,后续请求携带
text
小程序 后端 微信服务器
│ wx.login() 得 code │ │
│ ─── POST /login ──────> │ ─── code2Session ──────> │
│ │ <── openid/session_key ── │
│ │ 查找/创建用户、签发 token │
│ <── token ───────────── │ │
│ setStorageSync(token) │ │为什么不用 openid 直接当登录态
openid是固定值,一旦泄露可被永久伪造请求- 无法主动失效、无法控制有效期
正确做法是后端签发不透明的随机 token(如 UUID + 用户信息的缓存映射)或 JWT,并设置有效期(建议 7 天以内)。
请求携带与响应拦截
小程序端封装统一的请求模块:
js
// utils/request.js 核心逻辑
function request(options) {
const token = wx.getStorageSync('token')
return new Promise((resolve, reject) => {
wx.request({
...options,
header: { Authorization: `Bearer ${token}`, ...options.header },
success(res) {
if (res.data.code === 0) return resolve(res.data.data)
// 登录态失效:静默重新登录后重试一次
if (res.statusCode === 401) return reloginAndRetry(options)
wx.showToast({ title: res.data.message, icon: 'none' })
reject(res.data)
},
fail: reject
})
})
}关键点:收到 401 时静默重新走一遍登录流程并重试原请求,用户无感知。
安全要点
session_key绝不能下发给前端,它用于解密手机号等敏感数据,只能保存在服务端code是一次性的,不可重复使用,不可由前端直接调用code2Session(会暴露 secret)- 所有需鉴权接口服务端必须校验 token,不要信任客户端传来的用户 ID
- 手机号等敏感信息解密应放在后端完成,前端只展示结果
常见问题
- token 存哪儿:
wx.setStorageSync即可,不要放全局变量(小程序可能被杀掉重启) - 多端登录:如需"互踢",后端保存用户与 token 的映射关系,新登录时使旧 token 失效
- token 过期时间:太短会导致频繁重登,太长风险高;配合静默续期可以用较短的 7 天
小结
方案核心是「code 换 openid、后端签发自己的 token、401 静默重登」。这套流程我们已在多个商城类小程序中落地,稳定运行多年。
