网页手机号抓取程序(微信服务器使用code换取sessionKey加密时使用的sessionKey一致才可解密)

优采云 发布时间: 2021-11-05 13:14

  网页手机号抓取程序(微信服务器使用code换取sessionKey加密时使用的sessionKey一致才可解密)

  最近在做一个小的toC程序,把之前做的东西捡起来。但是我发现了一些之前踩过的坑,我又踩了一遍。

  实在想不起来了~花点时间做个笔记。

  重点说明:要获取微信用户绑定的手机号,需要先调用wx.login接口。

  原理:小程序获取的手机号码信息是微信服务器加密后的信息。微信服务器会根据wx.login下发的临时码对应的sessionKey对手机号信息进行加密。使用开发者服务器上的代码交换sessionKey,交换的sessionKey与加密信息时使用的sessionKey一致,才能解密成功。

  注意:服务端使用code交换的sessionKey不是加密时使用的sessionKey,导致解密失败。建议开发者提前登录。

  一、 登录授权要求

  由于业务限制,用户需要在登录小程序前对其手机号码进行授权,才能进入小程序。

  前端读取App.js入口文件中的本地存储,判断是否有手机号。如果有手机号,则直接刷新用户信息登录,如果没有,则需要通过登录授权流程登录。

  二、 公司内部小程序19年开发,登录授权设计。后台设计**两个界面**,登录和注册界面,更新用户信息界面。登录和注册接口逻辑:

  1、根据输入的参数code,调用微信auth.code2Session接口换取openId和session_key。

  2、 交换成功,查询user表中是否存在输入参数openId,如果存在则更新session_key,如果不存在则创建用户并保存openId和session_key。处理完毕后,将openId返回给前端。

  前端调用:

  在登录页面的onShow生命周期中,会调用该接口,将返回的数据记录在页面状态中。

  onShow: function () {

let that = this;

// 判断是否缓存手机号

that.data.purePhoneNumber = wx.getStorageSync("purePhoneNumber");

if (that.data.purePhoneNumber == '') {

wx.login({

success(res) {

WXrequest.post({

url: '/code2Session',

data: {

'jsCode': res.code

}

}).then(res => {

wx.setStorageSync('openid', res.data.openid);

that.data.openid = res.data.openid;

});

}

});

} else {

wx.showLoading({

title: '登录中' // 数据请求前loading

})

wx.switchTab({

url: '../mine/index'

})

}

}

  更新用户信息接口逻辑:

  1、 根据输入参数openId到user表查询session_key,结合输入参数encryptedData和iv解密得到手机号码。

  2、手机号解密后,更新用户信息,将用户信息返回给前端。

  前端调用:

  用户在获取手机号码后主动触发登录按钮并调用。

  getPhoneNumber: function (e) {

let that = this;

if (e.detail.errMsg == 'getPhoneNumber:ok') {

WXrequest.post({

url: '/getWXUserPhone',

data: {

'encryptedData': e.detail.encryptedData,

'openid': that.data.openid,

'iv': e.detail.iv,

}

}).then(res => {

// 存用户手机号及用户信息

wx.setStorageSync('purePhoneNumber', res.data.purePhoneNumber);

wx.setStorageSync('userInfo', res.data);

// 跳转首页

wx.showLoading({

title: '登录中'

})

setTimeout(function () {

wx.switchTab({

url: '../mine/index'

})

}, 1000)

})

}

}

  注意:该代码的有效期为五分钟。代码是在登录页面的onShow生命周期中获取的。如果用户在 5 分钟后打开页面并授权电话号码,则解密将失败。需要优化。

  二、 最近开发的toC小程序登录授权设计。后台同事将小程序登录+获取手机号设计成一个界面,叫做登录授权界面。接口逻辑:

  1、 根据输入参数code,先调用auth.code2Session接口,换取openId和session_key。

  2、 根据上一步交换的appId、encryptedData、session_key对数据进行解密,得到手机号码。

  3、查询用户表中是否存在openId,并进行逻辑处理。

  存在,判断用户手机号码与解析出的手机号码是否一致,一致接口返回用户信息;如果不一致,则更新手机号码,并将之前的手机号码记录在历史记录中。

  如果不存在,直接创建用户并返回用户信息。

  前端调用:

  由于代码,有效期为五分钟。获取登录页面onShow生命周期中的code并不能保证用户会在五分钟内对手机号码进行授权。

  所以获取手机号成功后,调用wx.login()获取code,然后调用登录授权接口。

  问题:

  先获取手机号,然后调用wx.login(),导致后台解析手机号失败,报错:session_key is invalid。

  根据以往的经验,我开始直接写代码,时间太长忘记了一些注意事项。报错后再次阅读文档。文档明确提醒:要获取微信用户绑定的手机号,需要先调用wx.login接口。

  注:阅读以下文档,了解微信对开放数据的验证解密,对为什么需要在获取手机号之前调用wx.login接口有更深的印象。

  解决方案:

  在登录页面的onShow生命周期中,每隔几分钟刷新一次登录状态。记录页面状态下的状态,获取手机号成功后发送到后台。

  componentDidShow() {

// 隐藏房子

Taro.hideHomeButton();

// code 用户登录凭证(有效期五分钟), 停留在当前页面每隔两分钟,重新刷新登陆态,否则后台解析session_key会失效

Taro.login({

success: (res) => {

this.setState({

code: res.code,

});

},

});

this.timer = setInterval(() => {

Taro.login({

success: (res) => {

this.setState({

code: res.code,

});

},

});

}, 60000 * 2);

}

// 获取手机号

getPhoneNumber(e) {

if (e.detail.errMsg.indexOf("getPhoneNumber:fail") != -1) {

if (e.detail.errMsg.indexOf("user cancel") != -1) {

toast("请不要重复点击、以免取消微信授权");

} else {

toast("允许授权将获得更好的服务");

}

} else {

this.setState({

loading: true,

});

Taro.request({

url: `${config.baseUrl}/user`,

method: "POST",

header: { "Content-Type": "application/json" },

data: {

code: this.state.code,

iv: e.detail.iv,

encryptedData: e.detail.encryptedData,

},

success: (res) => {

const redData = res.data.data || {};

if (res.data.code != 0) {

toast(res.data.msg);

} else {

Taro.setStorageSync(`${config.env}openId`, redData.openId);

Taro.setStorageSync(`${config.env}userId`, redData.userId);

Taro.setStorageSync(`${config.env}phone`, redData.phone);

this.props.dispatch({

type: "User/setUser",

payload: {

userInfo: redData,

},

});

this.setState({

loading: false,

});

}

},

fail: (err) => {

this.setState({

loading: false,

});

toast(err);

},

});

}

}

// DOM

this.getPhoneNumber(e)}

>

{this.state.loading ? "登录中" : "授权手机号"}

  三、详细了解微信登录授权机制原理。

  踩坑后,重新研究了OAuth2.0安全协议、小程序登录授权、开放数据验证解密等流程及底层原理。

  稍后花时间在笔记中组织它......

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线