简单了解小程序+node梳理登陆流程
程序员文章站
2022-04-09 12:43:40
希望通过小程序+node来整体的了解下小程序登陆的流程。如有不对欢迎在评论区指出
1. client: wx.login()
wx.login({
suc...
希望通过小程序+node来整体的了解下小程序登陆的流程。如有不对欢迎在评论区指出
1. client: wx.login()
wx.login({ success: ([code]) => { // 发送 code 到后台换取 openid, sessionkey, unionid } })
2. service: request()
服务端请求,需要的参数(js_code:client传的code;appid:小程序唯一标识申请账号时拿到;secret:小程序密钥申请账号时拿到;grant_type:默认值为 authorization_code)
// 请求方法 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:返回登陆态
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 // 查找数据库中是否已经存有openid,如果 hasopenid 为null说明是新用户 const hasopenid = await user.findbypk(openid) if(!hasopenid){ // 数据库存储openid,时间戳 user.create({openid,timespan:date.now()}) } handle(ctx, { token: encode(openid) }) } else { throw new error('登陆失败') } })
5.client:存储登陆态在storage
import { login_token } from '../../utils/localstorage' // 拿到token存储到客户端 wx.setstoragesync(login_token, token)
我在发起请求时将登陆态放在请求头中,相应的服务端可以从请求头中获取
header: { 'x-session': wx.getstoragesync(login_token) },
6.service:校验登陆态
module.exports = async function(ctx, next) { const sessionkey = ctx.get('x-session') const { id, timespan } = decode(sessionkey) // 查找数据库中是否存在该 openid,返回是一个数组,如果不存在则返回[] const targetlist = await getopenid(id) if (targetlist.length > 0) { // 如果超过设定的过期时间,标记isexpired字段为登陆过期 const onehour = 1000 * 60 * 60 * 24 if (date.now() - timespan > onehour) { ctx.state.isexpired = true // 跟前台约定,如果code=2说明登陆过期跳登陆页面 handle(ctx, '', 2, '登陆过期') } else { handle(ctx, '', 0, '登陆成功') } } else { // 通过ctx.throw可以直接抛出错误 ctx.throw(401, '登陆失败') }
整体流程图
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,
下一篇: ps怎么设计千与千寻的竖版书签?