天天看點

小程式koa mysql_微信小程式登入(Node.js-Koa2架構-本地伺服器)

導言:

使用Node.js的Koa2架構,在本地伺服器上實作微信小程式的登入過程。

該登入邏輯設計根據微信官方登入時序圖改編,并不是标準流程,僅供學習交流使用。

重點在思路,忽視了部分細節。

1.登入邏輯

小程式koa mysql_微信小程式登入(Node.js-Koa2架構-本地伺服器)

微信小程式登入流程

微信小程式中建立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.自定義登入态

小程式koa mysql_微信小程式登入(Node.js-Koa2架構-本地伺服器)

微信小程式登入态維護.png

2.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

}