一、之前的解密流程,会偶现“解密失败”,步骤如下:
1、点击 ‘getPhoneNumber’ 的按钮,弹出授权界面
2、调用 wx.checkSession 进行检查,success 的话就发送授权手机号解密接口;fail 的话就进行 wx.login 获取 code 后请求后端获取 openid/sessionKey,并将两个值缓存到本地,然后再进行手机号解密。
二、粗暴方式解密流程,会偶现“解密失败”,步骤如下:
1、点击 ‘getPhoneNumber’ 的按钮,弹出授权界面
2、调用 wx.login 获取 code 后请求后端获取 openid/sessionKey,然后进行手机号解密
探讨微信解密机制(个人理解,如有不对,请指出哟),如下:
1、点击 ‘getPhoneNumber’ 的按钮,弹出授权界面时,在微信后台会将数据进行加密,此时用于加密的 sessionKey-0 是微信后台已存的 sessionKey,这个 sessionKey 有可能是之前其他业务生成的,比如 wx.login(会刷新微信后台的 sessionKey)。
2、按照如上错误的步骤,进行 wx.login 获取 code 再获取 sessionKey-1,由于 wx.login 会刷新微信后台的登录状态,此时新生成的 sessionKey-1 和上一步中用于加密的 sessionKey-0 不是同一个,于是解密失败了。
3、重点:必须保持操作前后的 sessionKey 都是同一个,如果 wx.login 刷新了后台的 sessionKey,而之前的操作还是原来的 sessionKey,则会失败。
必现方式一(解密失败),如下:
1、正常授权解密后,关闭小程序一段时间,测试的时候大概 30-40 分钟左右,后台 sessionKey 过期了
2、重新打开小程序走之前的步骤,出现“解密失败”,然后第二次进行授权解密时,又成功了
必现方式二(解密失败),如下:
1、清理缓存后,点击授权登录(此时后台的sessionKey为空,所以无论怎么做登录和检查,都会解密失败),弹出界面后调用 wx.login 进行登录获取 sessionKey
2、授权解密,失败
3、再次点击授权登录(此时会获取第一步中登录生成的 sessionKey,与未过期的sessionKey一致),则进行解密,成功。
解决方案,如下:
基于对上面机制的理解,wx.login 方式获取的 sessionKey 必须在唤起授权弹窗前进行,必须保证授权弹窗时获取的 sessionKey 和 本地未过期的sessionKey是同一个。
1、在 app.js 的 onLaunch 中,先进行 wx.checkSession。success,则进行后续代码执行;如果 fail,则进行 wx.login 重新获取 sessionKey,后端同学将 sessionKey 存储至数据库,openid 是唯一的,可以作为主键。此时,会先于任何操作之前生成一个 sessionKey。
2、唤起授权界面,点击“允许”后,将 openid+iv+encryptedData 传给后端进行解密。
代码如下(IDE复制后没发改样式,const 等变量可能看不清,可以复制到自己的编辑器中查看哈):
然后在 onLaunch 中调用 onLogin.checkSession 进行前置 session 检查和获取
export const onLogin = {
// 检查 session 是否有效
checkSession(cb = () => {}) {
const _this = this;
// 检查登录态是否可用
wx.checkSession({
success () {
console.log('session success');
// session_key 未过期,并且在本生命周期一直有效
const { openid, session_key } = wx.getStorageSync('session');
cb(openid, session_key);
},
// 登录态失效了
fail () {
console.log('session fail');
_this._wxLogin((openid, session_key) => {
cb(openid, session_key);
});
}
});
},
// 微信获取 code 进行解密
_wxLogin(cb = () => {}) {
// 将 js_code 发送给后端获取 openId 和 sessionKey,并进行缓存
wx.showLoading({ mask: true });
wx.login({
success: ({ code }) => {
// 将 js_code 发送给后端获取 openId 和 sessionKey,并进行缓存
request({
url: `/wx/open/getSessionKey.json?code=${code}&clientIdentity=${CONFIG.clientIdentity}`,
onSuccess: ({ openid, session_key }) => {
wx.setStorageSync('session', { openid, session_key });
cb(openid, session_key);
},
complete: () => {
wx.hideLoading();
}
})
}
});
},
}
但是,我使用的是将code及 encryptedData 和 iv 一块传给后端,然后后端使用code获取openId和SessionKey,再拿获取的SessionKey 、iv和encryptedData 解密拿到手机号,但依旧会出现解密失败的问题。 按逻辑来看,此时的SeesionKey应该是最新的才对,为什么还会解密失败呢?
也就是后端要对每个用户维护一个sessionKey ,存到数据库中?
我在前端解密手机号也会出现解密手机号失败,解密方式如下:
1、点击 ‘getPhoneNumber’ 的按钮,弹出授权界面
2、调用 wx.login 获取 code 后请求后端获取 openid/sessionKey
3、前端解密手机号
偶尔会出现解密手机号失败,但是再次重复上面3个步骤解密手机号又可以了,请问是什么原因导致的呢?
话说我在解密手机号的前一个步骤获取sessionKey再传给后端解密能不能一步到位,这样sessionkey是不是就是唯一的值了呢?不再使用checkSession这个函数了,因为他无论成功还是失败都是success,我觉得这个思路应该是正解。有疑问请说出理由
上述逻辑中,也会一定概率出现授权手机号失败的情况。
由于code换sessionKey需要到服务端做请求,当onLaunch调用request超时,或者response太慢的时候,假定1s以上才返回response,还没等storage存储sessionKey,客户在画面上可能操作了授权手机号的按钮,这样,也会导致授权失败。
您好,有具体关于后端解密的代码吗?最好是java版本的