簡(jiǎn)單了解小程序+node梳理登陸流程
希望通過(guò)小程序+node來(lái)整體的了解下小程序登陸的流程。如有不對(duì)歡迎在評(píng)論區(qū)指出
1. client: wx.login()
wx.login({ success: ([code]) => { // 發(fā)送 code 到后臺(tái)換取 openId, sessionKey, unionId } })
2. service: request()
服務(wù)端請(qǐng)求,需要的參數(shù)(js_code:client傳的code;appid:小程序唯一標(biāo)識(shí)申請(qǐng)賬號(hào)時(shí)拿到;secret:小程序密鑰申請(qǐng)賬號(hào)時(shí)拿到;grant_type:默認(rèn)值為 authorization_code)
// 請(qǐng)求方法 const request = require('request') const url = https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code module.exports = { async getSession(code) { return new Promise((resolve, reject) => { request(url,{ method: 'GET', json: true }, (error, res, body) => { if (error) { reject(error) } else { if (body.errcode) { reject(new Error(body.errmsg)) } else { resolve(body) } } } ) }) } }
3.service:加密解密處理
const crypto = require('crypto') const secret = '2019_06' const algorithm = 'aes-256-cbc' function encode(id) { const encoder = crypto.createCipher(algorithm, secret) const str = [id, Date.now(), '2019'].join('|') let encrypted = encoder.update(str, 'utf8', 'hex') encrypted += encoder.final('hex') return encrypted } function decode(str) { const decoder = crypto.createDecipher(algorithm, secret) let decoded = decoder.update(str, 'hex', 'utf8') decoded += decoder.final('utf8') const arr = decoded.split('|') return { id: arr[0], timespan: parseInt(arr[1]) } } module.exports = { encode, decode }
4.service:返回登陸態(tài)
const { encode } = require('./lib/crypto') const jsonMine = 'application/json' const now = Date.now() function handle(ctx, data, code = 0, message = 'success') { ctx.type = jsonMine ctx.body = { code, data, message } } router.get('/login', async (ctx, next) => { const { code } = ctx.request.query const session = await login(code) if (session) { const { session_key, openid } = session // 查找數(shù)據(jù)庫(kù)中是否已經(jīng)存有openid,如果 hasOpenid 為null說(shuō)明是新用戶 const hasOpenid = await User.findByPk(openid) if(!hasOpenid){ // 數(shù)據(jù)庫(kù)存儲(chǔ)openid,時(shí)間戳 User.create({openid,timespan:Date.now()}) } handle(ctx, { token: encode(openid) }) } else { throw new Error('登陸失敗') } })
5.client:存儲(chǔ)登陸態(tài)在storage
import { LOGIN_TOKEN } from '../../utils/localStorage' // 拿到token存儲(chǔ)到客戶端 wx.setStorageSync(LOGIN_TOKEN, token)
我在發(fā)起請(qǐng)求時(shí)將登陸態(tài)放在請(qǐng)求頭中,相應(yīng)的服務(wù)端可以從請(qǐng)求頭中獲取
header: { 'x-session': wx.getStorageSync(LOGIN_TOKEN) },
6.service:校驗(yàn)登陸態(tài)
module.exports = async function(ctx, next) { const sessionKey = ctx.get('x-session') const { id, timespan } = decode(sessionKey) // 查找數(shù)據(jù)庫(kù)中是否存在該 openid,返回是一個(gè)數(shù)組,如果不存在則返回[] const targetList = await getOpenid(id) if (targetList.length > 0) { // 如果超過(guò)設(shè)定的過(guò)期時(shí)間,標(biāo)記isExpired字段為登陸過(guò)期 const oneHour = 1000 * 60 * 60 * 24 if (Date.now() - timespan > oneHour) { ctx.state.isExpired = true // 跟前臺(tái)約定,如果code=2說(shuō)明登陸過(guò)期跳登陸頁(yè)面 handle(ctx, '', 2, '登陸過(guò)期') } else { handle(ctx, '', 0, '登陸成功') } } else { // 通過(guò)ctx.throw可以直接拋出錯(cuò)誤 ctx.throw(401, '登陸失敗') }
整體流程圖
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,
相關(guān)文章
開(kāi)箱即用的Node.js+Mysql模塊封裝實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了開(kāi)箱即用的Node.js+Mysql模塊封裝實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01Nodejs讀取文件時(shí)相對(duì)路徑的正確寫(xiě)法(使用fs模塊)
本篇文章主要介紹了linux 環(huán)境 mysql寫(xiě)入中文報(bào)錯(cuò)的相關(guān)知識(shí)。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-04-04nodejs使用Express框架寫(xiě)后端接口的全過(guò)程
最近學(xué)習(xí)了基于前后端分離的開(kāi)發(fā)模式,我前端使用Vue框架,后端使用nodejs開(kāi)發(fā)API接口,下面這篇文章主要給大家介紹了關(guān)于nodejs使用Express框架寫(xiě)后端接口的相關(guān)資料,需要的朋友可以參考下2022-05-05Node.js中Request模塊處理HTTP協(xié)議請(qǐng)求的基本使用教程
這篇文章主要介紹了Node.js中Request模塊處理HTTP請(qǐng)求的基本使用教程,request也支持OAuth的簽名請(qǐng)求,很好很強(qiáng)大,需要的朋友可以參考下2016-03-03