最近,微信发布了小程序与小游戏获取用户信息接口调整。并在2018.5.10号正式实施,也就意味着用户登录接口不能使用wx.getUserInfo
去获取一些敏感信息。
PS:由于个人是用mpvue实现的,所以写法上会与原生有点奇怪,但这都不重要~
后台需要哪些信息?
小程序的一些后台配置我并不熟悉,就我司的开发流程大概需要:wx.login
的code
,getUserInfo
的iv
,encryptedData
。后台有了这些信息也就能够识别用户,拿到用户的一些信息,这就会让后台给前端一个token
可以理解为session
,因为小程序没有cookie
,所以需要一个额外的token
来标识用户,该token
一般放置于与后台约定的报文头内。
应该在哪些地方获得用户敏感信息?
用户的一些敏感信息如encryptedData
, iv
等,并不应该在用户一进入小程序就获取它们,而是等到使用一些敏感接口的时候才去让用户授权。
逻辑
在废弃getUserInfo
之后,最好的实践应该是在一些敏感接口,跳转至登录授权页面,只有用户点击授权页面的button
之后才接口才会往下走。
实现
了解以上以后,可以按照axios
的规则,封装自己的请求。这里假设已经封装好了。
所以我们需要对fetch
请求进行一层封装(注意:fetch
不是原生,而是你自己封装好的)。接口的调用方法基本长这样:fetch.get('someApi', data, { ignoreToken })
。
我们需要在请求之前做一层拦截器,每当发送请求时候没有设置ignoreToken
时候就应该判断本地是否有token
,如果有token
那就一路畅通无阻。如果没有则调入获取token的逻辑。
// 这里我们引用'minapp-api-promise'这个包,相当于把所有回调接口`promiseify`
// 每一个请求都会走这个请求后再去执行真正的request
import WXP from 'minapp-api-promise'
const { getStorageSync } = WXP
const requestInterceptor = (params) => {
return new Promise(async (res, rej) => {
let token = getStorageSync('token')
// 如何有设置ignoreToken
if (!params.ignoreToken) {
if (!token) {
// 调用自己写的getUserInfo,返回值为一个promise对象
// 这里相当于一个开关闸,只有getUserInfo()的返回值resolve()之后
// 该请求才会往下走,否则请求在这一直挂起
await getUserInfo()
token = getStorageSync('token')
}
}
if (token) {
req.header.auth = `${token}`
}
resolve(req)
})
}
接下来是最重要的,如何写getUserIno
let _getUserInfo = null
export const getUserInfo = () => {
if (_getUserInfo) {
_getUserInfo = new Promise((res, rej) => {
while(!getStorageSync(token)) {
try {
// 登录获得code
const data = await WXP.login()
// 该接口的用法在与如果你之前已经授权,
// 那么调用该接口直接执行success,否则执行fail
const user = await WXP.getUserInfo({
withCredentials: true,
lang: 'zh_CN',
})
// 判断用户是否授权过
const set = await WXP.getSetting()
// 发送一个忽视token的请求来获取token
const res = await fetch.get(getTokenApi, {
iv: user.iv,
encryptedData: user.encryptedData,
code: data.code
}, { ignoreToken: true })
wx.setStorageSync('token', res.data.access_token)
_getUserInfo = null
} catch(e) {
// 当用户未授权时
wx.navigateTo({ url: login页面 })
try{
await new Promise((resolve, reject) => {
// 如过你使用vuex可以直接放在store
// 没有的花你也可以放在原生的全局中
// 这样当跳转到用户授权页面时
// 不管用户授没授权,直接跳到最开始的循环。接下来自己脑补
wx.resolve = resolve; wx.reject = reject
}) catch(e) {
continue
}
}
}
}
})
}
return _getUserInfo
}
以上最让人疑惑的估计就是_getUserInfo
,我们来假设一进入页面就有3个敏感请求,那么第一个进来会使得_getUserInfo
为Promise
(假设为p1),并且跳入授权页面,这样会导致,其他2个一起await
p1这个promise
,只有当p1
跑通了才会接下来请求,那么p1
在等什么?等用户点击授权啊。
以上,有些模糊,之后会贴出实际代码。
当然,这里贴个图帮助大家理解。
小程序鉴权逻辑.jpg
网友评论