我一定是熬夜熬傻了,小程序后台获取用户信息居然发生了这件事
微信小程序获取用户手机号后端处理
前面我不是整理了一套微信小程序开发的api啊,起因是因为一个朋友接了一个私活,我们一起帮忙开发,然后再这个小程序里面有一个功能,就是通过微信小程序获取用户手机号后端处理,来看一下这个功能在微信官方是怎么定义的
注:程序员在自己的技术能力提升之后,闲来无事接一些小的开发任务,不沉重,但是长此以往,其实真的赚的不少,去吃顿好吃的旅个游不香吗?
好了,言归正传
官网流程概述
微信官方网页对于微信小程序获取用户手机号的处理描述如下
这页主要是对前端做法的描述,主要描述了前端应该提前通过wx.login登陆,或者进行登录态检查,以此避免刷新登录态的操作,避免出现服务端存的sessionKey不是最新的sessionKey从而出现敏感数据解密失败的问题。前端通过button触发bindgetphonenumber事件,拿到加密数据传给后端,后端通过解密算法解密。
后端逻辑
微信会对这些开放数据做签名和加密处理。开发者后台拿到开放数据后可以对数据进行校验签名和解密,来保证数据不被篡改。所以
1、前端通过调用接口(如 wx.getUserInfo)获取数据时,接口会同时返回 rawData、signature,其中 signature = sha1( rawData + session_key )
2、开发者将 signature、rawData 发送到开发者服务器进行校验。服务器利用用户对应的 session_key 使用相同的算法计算出签名 signature2 ,比对 signature 与 signature2 即可校验数据的完整性。
数据校验
后端拿到rawData后通过SHA1()算法对后端存储的sessionKey进行SHA1(rowData,sessionKey)加密,如果得到的signature与前端传来的signature一致,则校验成功。(获取用户手机号时数据校验不是必须的,所以此处只叙述逻辑并未实现)
数据解密
官方文档对数据解密的解释是这样的:
接口如果涉及敏感数据(如wx.getUserInfo当中的 openId 和 unionId),接口的明文内容将不包含这些敏感数据。开发者如需要获取敏感数据,需要对接口返回的加密数据(encryptedData) 进行对称解密。解密算法如下:
对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充。
对称解密的目标密文为 Base64_Decode(encryptedData)。
对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
对称解密算法初始向量 为Base64_Decode(iv),其中iv由数据接口返回。
所以笔者进行数据解密时采用了网络上搜的解密工具使用
我得到简洁的解密工具如下:
按照常理来说(以小编神奇的99%运气+1%实力)对比官网进行开发,一把不会出现问题,但是,没想到,阴沟里翻船了(最后得知bug原因的我被无情嘲讽)
代码在测试阶段出现了问题,抛出“BadPaddingException: Given final block not properly padded. Such issues can”开头的异常
经过问题排查,找出问题
1、微信小程序开发者工具获取的sessionKey有效期为5分钟,过时之后sessionKey就会解不出来
2、完善解密算法,增加处理异常的try–catch块,更换getInstance参数
解决上述两个问题之后,优化了工具,拿到用户手机号并成功返回。
返回格式与微信官方网站上一致。
格式如下
后端实现
此处贴上实现代码(后端接收由SpringBoot实现):
Controller层实现:
解密工具AesUtil实现:
好了,完美解决,哎,真的是,但是我觉得不是我实力的问题,肯定是微信官网没有写好(就这样,不容反驳,嘿嘿嘿)
好了,最后还是建议大家,没啥事的时候可以多去看一下官网的内容,或者自己debug一下源码,总能发现一些在平时开发的时候遇不到的问题,解决的问题的过程就是成长
我是小Q,热爱技术,也爱生活,坚持分享输出,让自己和读者都有收获!关注我来跟我一起变强吧。
关注公众号:Java架构师联盟,每日更新技术好文
版权声明: 本文为 InfoQ 作者【小Q】的原创文章。
原文链接:【http://xie.infoq.cn/article/61a3dd821e99b4df939761b11】。
本文遵守【CC BY-NC-ND】协议,转载请保留原文出处及本版权声明。
评论