微信小程序登录会话流程
惠民小程序小编了解到,微信小程序成为当下热门话题,下面从多个方面来谈谈微信小程序登录会话流程。 最新消息, 近日, 微信官方对小程序组件进行两个调整,给用户提供更自主的选择权。 1 打开其他小程序组件上线,用户点击后就可以直接跳转到其他小程序了。 2 新增打开小程序设置页组件,用户点击后可以进入设置页管理自己的各项授权信息。 ■开发者 背景微信小程序的使用可以快速的基于场景进行用户圈的建立推广,其中根据业务需要使用用户信息以及授权过程,主要用到的有微信在开发工具中已经封装好的api函数:wx.login、wx.getUserInfo、wx.checkSession、wx.getStorageSync、wx.request等 参数 类型说明userInfo OBJECT用户信息对象,不包含 openid 等敏感信息rawDataString不包括敏感信息的原始数据字符串,用于计算签名。signatureString使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息,参考文档 signature。encryptedDataString包括敏感数据在内的完整用户信息的加密数据,详细见加密数据解密算法iv String加密算法的初始向量,详细见加密数据解密算法 //调用成功后返回结果示例{encryptedData:"6exNeBvACX+EpzLNF2vYRhM0Z1tNZnBOYP0Qh6jQ4Ofv+69qY/RGVAB34aj4f364mkjAAD5pgDDJ41hGkkr/IaHJGioI3EhGSEQyrAfE1mPovV9s6Prg4rKedfBUerG4jEgXbS0GeERMtJ15tqEGz7qzcA49c1D1obZTuneImZq1vB1lXo3oUbnmK7LUAxQcgCQA==",errMsg:"getUserInfo:ok",iv:"X6PuFoueBpfgyjV9l9D6A==",rawData:"{"nickName":"xxx","gender":1,"language":"zh_CN","city":"","province":"","country":"Iceland","avatarUrl":"https://wx.qlogo.cn/mmsen/vi_s/0daYVYsscPNxEvALzBTsJarXwUmlxjZJZMHPM6NNLegH4wLRcRlsA1x4bsJg/132"}",signature:"c32wba325164258b9a332b6fdsdew2e520081348",userInfo:{avatarUrl:"https://wx.qlogo.cn/mmsen/vi_s/0daYVYsscPNxEvALzBTsJarXwUmlxjZJZMHPM6NNLegH4wLRcRlsA1x4bsJg/132",city:"",country:"Iceland",gender:1,language:"zh_CN",nickName:"xxx",province:"" }}敏感数据获取(加密数据encryptedData签名signature)对于encryptedData,开发者如需要获取敏感数据,需要对接口返回的加密数据( encryptedData )进行对称解密。也就是需要在开发者服务器上利用session_key解密获得的encryptedData,其结构如下: {"openId": "OPENID","nickName": "NICKNAME","gender": GENDER,"city": "CITY","province": "PROVINCE","country": "COUNTRY","avatarUrl": "AVATARURL","unionId": "UNIONID","watermark"://数据水印{"appid":"APPID",//敏感数据归属appid,开发者可校验此参数与自身appid是否一致"timestamp":TIMESTAMP //敏感数据获取的时间戳,开发者可以用于数据时效性校验}}自定义登录态环境:开发者服务器上数据:利用接口调用获得的开放数据或者解密后的敏感数据以及session_key操作:利用数据建立用户在小程序的唯一标识,以及发送自己定义的登录状态信息记录session(也可以是其他的信息记录)给客户端,session_key作为秘钥,必须保存在开发者服务器上(以前接口https://api.weixin.qq.com/sns...可以在小程序开发设置--服务器配置里设置为合法地址,现在不行了,只能使用第三方服务器进行接口调用)使用: 用户非首次登陆——>查询本地缓存中的自定义session——>获取到session向开发者服务器查询——>服务器上此session未过期可用——>用户可正常业务请求(这只是登陆情况比较普遍正常的一种) 2.登录 官方给的图示:(大概步骤可以看官方文档) 基本:其中使用wx.login()可以获得开发者服务器向微信接口服务器请求获得session_key等数据时所需要的参数code,开发者服务器以code+appid+app secret(小程序秘钥,管理后台可以获得)换取 用户唯一标识openid 和 会话密钥session_key。但每一次调用wx.login()都会更新微信接口服务器上的session_key。 首次登录 获取登录凭证code——>发送至开发者服务器构造接口( appid + app secret + code) 请求 微信接口服务器数据——>返回用户数据密钥session_key 和唯一标识openid给开发者服务器——>根据session_key 和 openid等生成自定义的第三方session,存储session_key至开发者服务器,不能将session_key发送至客户端,防止敏感数据泄露——>将第三方自定义登录信息session发送至客户端——>保存自定义第三方登录态信息session到本地缓存,登录成功,可以设置一个登录标识flag,使flag=true表示首次登录成功,进行相关的处理操作。其中,登录校验凭证接口(在开发者服务器中调用,小程序中无法使用此接口)为: https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code appid小程序唯一标识 secret 小程序的 app secret js_code是wx.login登录时获取的凭证code grant_type 填写为 authorization_code 具体伪代码如下: /** * 我把这一步封装成一个函数,以后再调用那些需要登录后才有权限访问的后台服务时. * 可以使用使用这个函数操作,基本逻辑,还可以进行扩展 * @url: 开发者服务器登录服务接口 可设置默认值 * @key: 存入本地缓存的第三方自定义登录session的键值 * @callback : 需要用到登录服务的回调函数(或函数集合) */functionLogin(key,url,callback){ // 首先使用wx.login获取登录凭证code并发送给开发者服务器 wx.login({success: function(res) {if (res.code) {//发送code给开发者服务器以获取session_key和openidwx.request({url:url,data: {code: res.code},//发送至开发者服务器成功success: function(res) {//开发者服务器获得session_key和openid成功并返回了//第三方自定义session或者解密数据等json格式数据res给客户端if(res.has3rdSession){//登录成功,将第三方session存入本地缓存console.log("登录成功")wx.setStorageSync(key,res.3rdSession)//设置登录标识为truethis.setData{flag:true}//进行后续回调处理callback(res)....}else{//没有返回第三方自定义session,登录失败console.log("登录失败")....}}})} else {//没有获取到登录凭证code,登录失败console.log('登录失败!' + res.errMsg)....}}})}非首次登录 wx.getStorageSync()查询本地缓存中是否有我们自定义的session登录态信息,有的话证明不是第一次登录,此时先查询微信接口服务器上的用户session_key是否过期,如果过期了,不管我们自己定义的session如何,都要重新登录,设置登录标识flag为false;如果没有过期,那么可以向开发者服务器发送sessio查询用户信息,如果开发者服务器告诉我们自己定义的session过期了,那重新登录,设置登录标识flag为false,如果没有过期,则查询是否有这个session来获得用户的相关信息,具体伪代码如下: /** - 我把这一步封装成一个函数,以后再调用那些需要登录后才有权限访问的后台服务时. - 可以使用使用这个函数操作,基本逻辑,还可以进行扩展 - @url: 开发者服务器服务接口 - @key: 自己定义的session存储在本地缓存中的键名 - @callback : 需要用到登录服务的回调函数(或函数集合) - @others : 其他需要用到的数据等参数 */function doRequestWithSession(key,callback,others){try {var value = wx.getStorageSync(key)if (value) {// 存在自定义登录session,非首次登录// 查询 用户密钥session_key是否过期wx.checkSession({success: function(){//session_key 未过期,并且在本生命周期一直有效//向开发者服务器发送自定义session查询用户信息wx.request({url: url,data: value,//本地缓存的自定义Session值 可以加上其他需要的数据others等success: function(res) { if(res.hasSession){//查询成功,开发者服务器上有我们自定义的session//根据返回结果进行对应的操作,先判断session是否过期//如果我们自定义的session已经过期if(res.expired){console.log("session过期,重新登录")//设置登录标识为falsethis.setData{flag:false}wx.login() //重新登录 或者 返回错误码....}else{//没有过期,返回的结果则可以是用户的相关信息//进行相关操作 登录成功 console.log("欢迎回来") callback(res) ....}}else{//开发者服务器上没有我们自定义的session,重新登录console.log("无此session,重新登录")//设置登录标识为falsethis.setData{flag:false}wx.login() //重新登录 或者 返回错误码....} }})},fail: function(){// session_key 已经失效,需要重新执行登录流程//设置登录标识为falsethis.setData{flag:false}wx.login() //重新登录 或者 返回错误码....}})}else{//本地缓存中没有自定义的session登录态信息,则进行首次登录或者后续处理//设置登录标识为falsethis.setData{ flag:false}wx.login() //登录 或者 返回错误码....}} catch (e) {// 异常处理....} }条件判断登录需要用到登录权限的服务时,可以使用条件判断伪代码: if(this.data.flag){//已经登录过,非首次登录doRequestWithSession(key,others)....}else{//没有登录过,可以进一步检查本地缓存是否有3rdSessiondo other things....}3.获取安全的原始数据 在第一部分已经说过敏感数据和开放数据,可以用wx.getUserInfo获得开放数据,但是没有登录获取解密密钥session_key是无法解密敏感数据的,所以开放数据中,没有登录的话,我们只能获得用户昵称、头像、城市、性别、国籍等,并没有可以标识用户的唯一id。所以如何拿到我们的安全的原始数据,只有:获取开放数据——>获得登录权限,开发者服务器获得密钥session_key校验签名解密数据——>返回解密数据,包含有openid。伪代码: a.wxml 文件: //wx.getUserInfo接口有调整,使用该接口将不再出现授权弹窗,要使用 |