LeeJim/better-fe

小程序开发总结(session部分)

Opened this issue · 0 comments

最近刚完成了一项小程序的开发任务。彻彻底底地从零开始,其中遇到了不少坑要填,因此来总结一下,希望能帮助到其他人,避免重复踩坑。

登录态维护

每个人开发小程序,都希望用户能持续使用自己开发的小程序,那么维护用户的登录态就是首要的任务。

无cookie

首先,第一个需要踩的坑就是无cookie的登录态要如何维护。

微信官方提供了一个流程图,我们可以先看看:

微信官方登录时序图

简而言之:

  1. 在小程序上通过wx.login()获取code
  2. code传到自己的服务器,然后将小程序的secretappid与微信服务器交换openidsession_key
  3. session_key加上随机数生成sessionId,然后openidsession_key存在session
  4. 小程序将sessionId存起来,每次访问都带上这个sessionId

小程序获取code

在小程序的app.js文件里,onLaunch函数调用我们写好的login函数:

wx.login({
  success: function (loginResult) {
    wx.getUserInfo({
      withCredentials: true,
      success: function (userResult) {
        // doLogin 就是将这些数据发送到服务器
        doLogin(null, {
            code: loginResult.code,
            encryptedData: userResult.encryptedData,
            iv: userResult.iv
        })
      }
    })
  }
})

服务器接受到这些数据,就可以和微信服务器交换数据了,这时我们拥有的数据就是openidsession_key

解密用户信息

通过小程序传过来的和encryptedDataiv,然后还有刚才获取的session_key,我们就能解密用户的信息,通过对比解密出来的openid和微信交换来的openid对比,即可知道用户信息的正确性。

sessionId生成:

function generateSessionId() {
  return crypto.randomBytes(32).toString('hex')
}

按理说,我们生成了sessionId,然后将对应的用户信息存在session里就大功告成了。

但是这样的话,很容易被伪造的暴力的伪造sessionId攻击。因此,需要再进一步,生成另外一个校验数据称为sessionkey简称sKey,这时就使用到刚获取到的session_key

function generateSkey(sessionKey) {
  const sha1 = (message) => {
      return crypto.createHash('sha1').update(message, 'utf8').digest('hex')
  }

  return sha1(appid + secret + sessionKey)
}

此时我们的sessionkey就是一个前面随机生成的sessionIdvalue则为:

{
  userinfo,
  session_key,
  sKey
}

然后每次sessionId传递过来的时候,我们获取对应的session_key,然后调用generateSkey生成sKey,然后和session里面的sKey对比即可。

此时,session的生成大功告成了!

两个登录态的问题

首先,调用微信生成的code的login()函数是有时效的,大概5分钟。

我们生成的session也是有时效的。这样就有两个登录态任一出现失效的情况。因此我们需要处理两个的失效问题。

小程序登录态

官方提供了wx.checkSession()方法给我们验证登录态是否失效。因此这个失效的话,我们就重新调用之前写好的login函数

session失效

这个失效的问题就比较麻烦。很有可能就是发送某一个请求的时候发现session失效了。

因此我们可以在app.jsonShow()里发送请求到服务器测试session是否过期。过期的话就重新调用login函数。