微信小程序登录(Node.js-Koa2框架-本地服务器)
导言:
- 使用
Node.js
的Koa2
框架,在本地服务器上实现微信小程序的登录过程。
- 该登录逻辑设计根据微信官方登录时序图改编,并不是标准流程,仅供学习交流使用。
- 重点在思路,忽视了部分细节。
1.登录逻辑
微信小程序登录流程-
微信小程序中新建
index
页面,设计“登录”按钮,点击按钮触发以下事件。 -
在微信小程序的客户端调用接口
wx.login()
来获取code
(登录凭证)。 -
调用接口
wx.request()
将code
发送到开发者服务器。 -
在开发者服务器处,将从客户端传递过来的
code
以及小程序本身的appid
和appsecret
组合成一段URL
:
// GET请求
// APPID,SECRET,JSCODE分别替换为appid,appsecret和code的值
https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
-
在开发者服务器上发送上述
GET
请求,微信服务器会返回openid
和session_key
的值。 -
通过算法(可以是当前时间或随机数等等),生成
_3rd_session
。 -
将
openid
和session_key
封装成JSON
对象。 -
生成的
_3rd_session
作为key
,封装好的JSON
对象作为value
,存储到Redis
数据库中,并设置好合适的过期时间。 -
将生成的
_3rd_session
发送到客户端中。 -
在客户端中,调用接口
wx.setStorageSync()
,把_3rd_session
存入缓存中。 -
完整的登录流程结束。
2.自定义登录态
微信小程序登录态维护.png2.1 登录验证
用户登录后重新进入小程序时,调用接口wx.checkSession()
来检测登录态。若有效,则继续进入下一页面;若失效,则重新发起上述的登录流程。
2.2 登录态维护
-
用户已经登录成功,进入下一级页面。
-
用户发起敏感请求(如删除,修改,添加等操作),调用接口
wx.request()
时,使其携带缓存中的_3rd_session
。 -
开发者服务器响应请求前,先到
Redis
数据库中查询有无键值为_3rd_session
的记录。 -
若记录存在并有效,则正常响应请求。
-
若记录不存在或已经失效,则拒绝请求,提醒用户未登录。
3.前期准备
-
获取
appid
:微信开发者工具 > 菜单栏 > 详情 > 第一行AppID。 -
获取
appsecret
:打开微信公众平台 > 登录 > 开发 > 开发设置 > AppSecret。 -
微信小程序:设置
index
页,放置“登录”按钮,绑定事件函数onMyLogin()
。 -
Node.js Koa2
框架的基本配置,不再赘述。 -
Node.js module
:redis
,koa2-request
的基本使用,不再赘述。
4.登录实现(核心代码)
客户端登录:
onMyLogin(){
wx.login({//获取登录凭证
success: res => {
wx.request({
url: 'http://127.0.0.1:3000/user/wxlogin', // 登录路由
method: 'POST',
data: {// 发送appid,appsecret和code到开发者服务器
"APPID": "wx9215321878b739b6",
"SECRET": "63ec9a12c928611a642144aa5a615fc1",
"JSCODE": res.code
},
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
success(res) {
//将登录凭证_3rd_session存入缓存
wx.setStorageSync("_3rd_session", res.data)
}
})
}
})
}
开发者服务器处理登录请求:
const router = require('koa-router')()
const koa2Req = require('koa2-request')
const redisClient = require('../db/redis')
const {REDIS_EXPIRES} = require('../conf/db')
router.prefix('user')
router.post('/wxlogin',async (ctx, next) => {
// 接收appid,appsecret,code
const {APPID,SECRET,JSCODE} = ctx.request.body
// 组合url
let url = 'https://api.weixin.qq.com/sns/jscode2session?appid='+APPID+'&secret='+SECRET+'&js_code='+JSCODE+'&grant_type=authorization_code'
// 向微信服务器发送请求
let res = await koa2Req(url);
// 获取session_key和openid
const {session_key,openid} = JSON.parse(res.body);
// 生成_3rd_session
const _3rd_session = `${Date.now()}+${Math.random()}`
// 存入Redis并设置过期时间
const result = await redisClient.set(_3rd_session,JSON.stringify({session_key:session_key,openid:openid}))
await redisClient.expire(_3rd_session,REDIS_EXPIRES)
// 返回_3rd_session
if(result){
ctx.body = _3rd_session
}
})
登录态检验的中间件:
const redisClient = require('../db/redis')
loginCheck = async (ctx,next) => {
// 查询数据库,判断_3rd_session是否存在且有效
const res = await redisClient.get(ctx.request.body._3rd_session)
if(res){
ctx.request.body.openid = JSON.parse(res).openid
await next()
}else{
ctx.body = "未登录!"
}
}
module.exports = {
loginCheck
}