最近刚完成了一项小程序的开发任务。彻彻底底地从零开始,其中遇到了不少坑要填,因此来总结一下,希望能帮助到其他人,避免重复踩坑。
登录态维护
每个人开发小程序,都希望用户能持续使用自己开发的小程序,那么维护用户的登录态就是首要的任务。
无cookie
首先,第一个需要踩的坑就是无cookie
的登录态要如何维护。
微信官方提供了一个流程图,我们可以先看看:
简而言之:
- 在小程序上通过
wx.login()
获取code
- 将
code
传到自己的服务器,然后将小程序的secret
和appid
与微信服务器交换openid
和session_key
- 将
session_key
加上随机数生成sessionId
,然后openid
和session_key
存在session
里 - 小程序将
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
})
}
})
}
})
服务器接受到这些数据,就可以和微信服务器交换数据了,这时我们拥有的数据就是openid
和session_key
。
解密用户信息
通过小程序传过来的和encryptedData
和iv
,然后还有刚才获取的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)
}
此时我们的session
的key
就是一个前面随机生成的sessionId
。value
则为:
{
userinfo,
session_key,
sKey
}
然后每次sessionId
传递过来的时候,我们获取对应的session_key
,然后调用generateSkey
生成sKey
,然后和session
里面的sKey
对比即可。
此时,session
的生成大功告成了!
两个登录态的问题
首先,调用微信生成的code的login()
函数是有时效的,大概5分钟。
我们生成的session
也是有时效的。这样就有两个登录态任一出现失效的情况。因此我们需要处理两个的失效问题。
小程序登录态
官方提供了wx.checkSession()
方法给我们验证登录态是否失效。因此这个失效的话,我们就重新调用之前写好的login
函数
session失效
这个失效的问题就比较麻烦。很有可能就是发送某一个请求的时候发现session
失效了。
因此我们可以在app.js
的onShow()
里发送请求到服务器测试session
是否过期。过期的话就重新调用login
函数。