.post('/user/bindinfo', (req, res) => {
var user = req.user
if (user) {
var {encryptedData, iv} = req.body
var pc = new WXBizDataCrypt(config.appId, user.sessionKey)
var data = pc.decryptData(encryptedData, iv)
Object.assign(user, data)
return res.send({
code: 0
})
}
throw new Error('用户未登录')
})
.post('/user/bindphone', (req, res) => {
var user = req.user
if (user) {
var {encryptedData, iv} = req.body
var pc = new WXBizDataCrypt(config.appId, user.sessionKey)
var data = pc.decryptData(encryptedData, iv)
Object.assign(user, data)
return res.send({
code: 0
})
}
throw new Error('用户未登录')
})
体验过小程序的童鞋应该都知道,最初进入一个新的小程序,会让我们进行一系列授权操作,同意过后就可以正常使用了,并且在下次进入的时候依然保持授权后的状态
那这一系列操作是怎么完成的呢?我们的授权登入态是怎么维护的呢?
下面就来说说我根据官方给出的方法来写出的维护登录态的方法吧
登录态维护
微信小程序的运行环境不是在浏览器下运行的,所以就不能用浏览器下那套cookie实现机制来维护登录态了,但我们可以仿浏览器来实现
官方文档给出了
wx.login()
的方法来获取用户登录态:登录时序图
小程序在调用
wx.login()
时会获取到临时登录凭证code,然后将code发送到后台服务器前端具体实现如下(app.js)
后台服务器再通过code去请求微信服务器,换取对应的用于用户唯一标识的openid和会话密钥(解密用户的敏感信息)session_key
后端具体实现如下(server.js)
后台服务器紧接着可以根据用户标识来生成自定义登录态,以便于维护后续业务逻辑中前后端交互时的身份
需要注意的是,后台服务器在拿到session_key、openid等字段时,不应该直接作为用户的标识或者session的标识,而应该自己生成一个session登录态(可以参考登录时序图),在保证其安全性的角度上不设置较长的过期时间
后端具体实现如下(server.js)
session通过响应头派发到小程序客户端之后,可将其存储在storage中,然后每次发请求时再加在请求头上,用于后续通信的登录态校验
前端具体实现如下(util.js)
响应头拦截器
请求头拦截器
以上就是整个登录态维护的实现方法,总结来说就是
调用
wx.login()
得到code
后请求服务器获取openid
和session_key
缓存到服务器当中其中生成一个随机数为
key
,value
为openid
与session_key
然后返回到小程序通过
wx.setStorage
('token',得到的随机数key)存在小程序当中每当我们去请求服务器时带上
token
即可给服务器读取从而判断用户是否在登录自定义登录态有效期
上述维护登录态的实现,我们已经了解到最关键的是生成与
openid
与session_key
对应的key
值,来保持用户唯一身份的识别而我们每调用一次
wx.login()
时,就会更新用户的session_key
,从而导致旧的session_key
失效所以我们必须明确只有在需要重新登录时才调用
wx.login()
那怎么确定什么时候才是需要重新登录的呢?换句话说就是怎么知道
session_key
的有效期呢?我们可以先看下官方文档
也就是说小程序通过
wx.login()
接口获得的用户登录态是具有一定的时效性的,可以通过wx.checkSession()
来判断登录态是否过期,从而决定是否更新登录态前端具体实现如下(app.js)
微信授权&获取用户数据
通过
wx.login()
实现登录态维护之后,我们就可以通过wx.getUserInfo()
获取用户信息、wx.getPhoneNumber()
获取手机号信息了得到的用户数据包含两部分,一部分是敏感信息,需要从密文中解密出来,密文在encryptedData这个字段中,去请求后台服务器去解密然后就可以得到敏感信息并保存下来了;另一部分是不敏感的信息,在result的userInfo里
如下图所示
有一点需要注意的是,微信5月份出了最新的策略,这俩操作都需要用户主动点击点击按钮,完成统一授权后才能触发
wxml代码如下(index. wxml)
在实际项目开发中,我们每进行一次不同的授权操作,都会将微信服务器请求授权的用户数据返回到后台服务器,然后写入统一的用户信息接口,再返回给小程序
每次授权后前端也都需要进行用户信息更新,以便于将所有有关用户的信息都存于统一的接口,便于调用
如果每进行一次授权操作,都重新写一遍请求后台用户信息接口的逻辑,难免让代码显得冗余
那正确的操作是怎样的呢?
我们可以在入口app.js文件中声明调用的后台接口,将用户信息存入全局定义的数组中(暂且称之为userInfo)
前端代码如下(app.js)
这样即使在授权过后,再次使用该小程序时,我们也能够从全局直接拿到用户信息,然后在各个页面调用全局数据即可
比如微信授权页面(index.js)
那前后端是怎么实现微信授权操作中从微信服务器读取数据然后存入后台数据库的呢?
获取用户信息(头像昵称等)
前端代码如下(index.js)
服务端接口代码如下(server.js)
获取用户手机号
前端代码如下(inde.js)
服务端接口如下(server.js)
代码
可见我的wxapp-authorization-demo