
小程序登录鉴权没有 Cookie 会话可用。用户进页面后先调 wx.login 拿临时 code,再由服务端换取 openid 与 session_key,最后签发出本站登录凭证。任一环写错都会导致「登录成功却接口 401」。
一、登录链路与 code 换取会话
wx.login 只取一张一次性票据 code,身份校验在服务端与微信之间完成,code 必须交给后端处理。
1. wx.login 拿到临时 code
code 五分钟有效且只能用一次,前端应立刻发给登录接口,不要缓存。回调里没有 openid。
// 前端:登录换取本站凭证
wx.login({ success: ({ code }) => wx.request({
url: "https://api.example.com/auth/login", data: { code },
success: (res) => wx.setStorageSync("token", res.data.token),
})});
2. 后端 code2session 换取 openid
服务端带 appid、secret 调用 code2session,成功返回 openid 与 unionid,openid 是本小程序的用户标识。
// 后端:用 code 换取身份
const r = await axios.get("https://api.weixin.qq.com/sns/jscode2session",
{ params: { appid, secret, js_code: code, grant_type: "authorization_code" } });
const { openid } = r.data; // session_key 只留服务端
二、登录态签发与接口鉴权
微信不提供长期凭证,wx.checkSession 只能判断 session_key 是否有效,业务需自签登录态。
1. 自定义 token 的签发与鉴权
服务端生成随机 token,把 token 与 openid 的映射写进 Redis 并设过期时间。需登录的接口都挂 auth 中间件校验。
// 后端:签发 7 天登录态 + 鉴权中间件
const token = crypto.randomBytes(24).toString("hex");
await redis.set(`sess:${token}`, openid, "EX", 604800);
async function auth(req, res, next) {
const t = (req.headers.authorization || "").slice(7);
const uid = t && await redis.get(`sess:${t}`);
if (!uid) return res.status(401).json({ code: 401 });
req.user = { openid: uid }; // 滑动续期
next();
}
前端把 token 存进 wx.setStorageSync,每个请求在头里带上;遇到 401 应清理并重新登录。
三、常见问题与安全要点
1. session_key 不得下发到前端
session_key 是解密用户数据的密钥,下发到前端等于公开,解密都应在服务端完成,secret 更不能写进小程序代码。
2. 登录态过期与并发处理
多端登录会产生多个 token;若要单端在线,需维护 openid 到 token 的索引,过期后前端可静默重登。
关键配置提示
- code 五分钟有效且一次性,必须即时交换,不要缓存。
- session_key 与 secret 只留服务端,前端只持有自定义 token。
- token 存 Redis 设过期时间,接口统一走鉴权中间件。

快来评论,快来抢沙发吧~