基于一个好玩儿的聊天室理解小程序 session 管理

panda-chat-room

小程序版 websocket 聊天室。 从服务器到小程序客户端配置基础教程。html

在本教程内咱们将在小程序内实现一个基本的 websocket 聊天室, 计划实现如下功能:html5

  1. 微信用户登陆「 小程序 session 管理 」☑️
  2. 用户间文本交流 「 websocket 实现 」☑️
  3. 用户间发送图片等富媒体信息 「 文件的储存及相关逻辑 」☑️

熊猫聊天室
图片描述


小程序已挂,缘由是我的开发者没法提交信息交流类小程序, 不过在本地运行 demo 仍是没问题的。node

写的有纰漏的地方还请你们指出,在 SF 下留言或在 本项目 git 内提 issue ,咱们一块儿进步 ^o^

聊天室基础配置

小程序端的聊天室信息流其实很是简单, 而本教程就借助一个好玩儿的小程序聊天室来进一步理解小程序中的 session 实现。 git

我在服务器端环境搭建及配置主要参考腾讯云实验 基于 CentOS 搭建微信小程序服务github

咱们在此先要理解小程序端为什么没法实现 session, 以及如何在小程序实现 websocket 通讯。web

小程序并不是嵌套在微信内的 html5 网页, 它并非从 url 访问到的。 咱们只能本身实现相似会话的东西, 好在官方已经提供了相应的套件来实现 session。 即 wafer-client-sdk 和 node 中间件 wafer-node-session, 咱们依照文档就能简单地实现 session。算法

腾讯云 wafer 项目下有不少类似项目「大部分须要配合腾讯云进行一键部署」, 若是咱们只须要实现小程序 session 管理的话, wafer-client-sdk 和 node 中间件 wafer-node-session 便可。

在服务器端咱们使用了 ws 包来实现 websocket ,没有使用 socket.io 的缘由是 socket.io 须要客户端有额外的脚本才能实现通讯。npm

在小程序端咱们引入 wafer-client-sdk 套件使服务器能够获取 session。小程序

主要逻辑分为几个简单函数, 固然你须要先配置请求的服务器域名和小程序帐号密码。微信小程序

// 引入 session 套件, 里面封装了 wx.login, wx.getUserInfo 等操做
const wafer = require('../../vendors/wafer-client-sdk/index')

// 用于登陆使服务器得到 session, 而后服务器返回的 session 里就会包含用户信息了, 用来在 websocket 里返回发信息用户的头像 url
function login(){
  .....
}

// 用于有新信息时更新数据, msg 指信息, ad 指 websocket 传回的信息 id, 用于 scroll-into-view 滚动
pushMsg(msg, ad) {
  .....
}

// 用于监听 websocket 链接
listen(){
  .....
}

//  用于小程序发送 websocket 信息
send(){
  .....
}

基本就是这些, 关于 websocket 通讯过程是这样的:

  1. 客户端发送信息给服务器 m1
  2. 服务器收到信息后根据条件返回给客户端 m2
  3. 每一个客户端收到 m2 后更新视图

固然最开始是要与服务器端 websocket 链接的, 只有每一个链接了的客户端才能够交流信息。

小程序 session 解析

对于 session 的实现咱们在服务器端使用了 wafer-node-session 即为链接提供 session 能力。 在小程序端咱们配套使用了 wafer-client-sdk, 这里面封装了 wx.request、 wx.login 等逻辑, 实现了小程序端的用户登陆、session 设置。

关于小程序端的 session 获取问题主要有以下几个步骤

  1. wx.login 获取 code
  2. wx.request 发送 code 给本身的服务器
  3. 服务器收到 code 配合 appId 和 appSecret 发送给微信服务器换取 openId 和 sessionKey
  4. wx.getUserInfo 会获得 rawData、signature、encryptedData、 iv, 咱们须要把它们发送到本身服务器。 咱们构建本身的 signature2 = sha1(sessionKey + rawData) , 比对 signature 和 signature2 就完成了数据校验
  5. 服务端经过 aes-128-cbc 算法对称解密 encryptedData 和 iv 而后获得 userInfo 此次获得的 userInfo 里还包含 openId 等信息 「若是在微信开放平台绑定小程序就会获得 unionId」
  6. 服务端构建 req.session 对象并返回给小程序,里面包含 id、 userInfo、 sessionKey「小程序传到服务器的」、skey 「服务器本身根据sessionKey + appId + appSecret 生成, 有过时时间」。 而咱们本身生成的 skey 是有设置过时时间的, 但小程序端的 session 也有本身的过时时间 「应该是微信按使用小程序的频率来动态设置过时时间的。 wafer 会自动调用 wx.checkSession 检查是否过时, 过时了就 wx.login」。

在咱们的 demo 中就出现了服务器 session 已通过期而本地 session 还没过时的状况。 而 websocket 每次发送信息都须要从 req.session 内获取用户头像, 因此会致使 websocket 链接失败。 可是在小程序端 session 未过时,即在服务器端的 sessionKey 和小程序的 sessionKey 不一致了 「客户端 sessionKey 还在而服务器的 sessionKey 已通过期销毁」, 致使比对失败。 那怎么办呢? 从新请求呗! 可是由于 wafer 封装了 session 管理 「小程序端 session 过时后才会从新请求」 存在 session 缓存的缘故, 小程序并无从新发送信息给本身的服务器进而生成新的 sessionKey, 因此咱们在每一次 wx.sendSocketMessage 发信息的时候都要检查服务器端的 session 状况, 这里须要作简单的判断「websocket 信息有错误就清除本地 session」让小程序从新请求服务器。

websocket 信息发送

既然要发送信息「即产生数据」, 那么这些信息都储存在哪里呢? 在发送文本信息时, 服务器端收到数据后只作简单地处理便返回给小程序, 这时的数据应该是储存在服务器内存中。 由于 websocket 在收到请求后简单处理了字符串信息直接返回给小程序, 那咱们发送其它富媒体信息时,也能够以二进制的方式发送给 websocket 服务器, 而后从新返回给客户端 「即 websocket 只作文件中转」,相关实现 websocket-stream 。 貌似看起来很复杂,在这里我使用了国内的 paas 服务商 leanCloud 的储存服务 「即小程序端把发送的文件储存在云端,返回一个文件地址」,而后咱们把这个文件信息进行标注「即只发送文件的 url 信息, 小程序端判断请求是不是文件进而显示」。 固然你也能够发送视频或者音频, 把他们都保存在云端, 只发送其相应的 url 便可。 咱们这里的 websocket 服务器只作一个文件中转的功能, 而文件的存储交给云端来负责。

panda-chat-room 项目源码

项目源码 ☑️

相关文章
相关标签/搜索