小程序的登陆和数据解密全解析

不知不觉已经一个月没有写东西了,堕落的日子竟然过的这么心(chou)安(bu)理(yao)得(lian),罪过啊。javascript

好了,回到正文来,聊我们的小程序。css

致敬

登陆大部分逻辑代码通通来自手把手教会你小程序登陆鉴权前端

登陆流程

上图是官方给出的登陆流程,咱们来捋下逻辑。java

一、用户使用wx.login获取临时code,有效期为5分钟git

二、将临时code传到咱们本身的后端服务,调用微信的API获取用户的session_keyopenidgithub

三、后端自定义新的密钥并关联返回的session_keyopenid,将新的密钥返给前端ajax

四、前端发送请求的时候,带着密钥,后端进行解析后返回数据算法

session_key和openid

一、session_key会话密钥,用来肯定会话的操做的有效性和用来加密解密用户数据,服务器本身存储便可,不该该将密钥返给前端和对话使用数据库

二、openid用户惟一标识,一样只用于服务器,能够用来标识用户的惟一性编程

接下来,咱们说下它们的获取,经过服务端调用微信API获取

API:https://api.weixin.qq.com/sns/jscode2session

参数以下:

// 小程序页面
wx.login({
	success:(ret)=>{
		wx.request({
			url: 'http://test.com', // 后端服务器
			data:{
				code : ret.code
			}
		})
	}
})

复制代码

后端服务咱们使用request模块来发送请求

// 后端服务
let options = {
  url: 'https://api.weixin.qq.com/sns/jscode2session',
  qs:{
      appid: appid,  
      secret: secret,
      js_code: code,
      grant_type:'authorization_code'
  }
}

// 默认请求方式是get
request(options, (err, response, body) => {
	if(err) return err
	return body  // {openid:'openid', session_key:'session_key'} 不是真正的返回 看下面的代码
})

复制代码

生成新的密钥 skey

上面咱们获取了session_key和openid,下文两个字断称keyID,接下来咱们生成一个新的密钥返回前端并将新密钥关联keyID。

咱们使用crypto模块的sha1算法生成密钥

const crypto = require('crypto')

function getShaKey(data){
	return crypto.createHash('sha1').update(data, 'utf8').digest('hex')
}
复制代码

上面的代码返回咱们就改为这个新的skey,前端将这个密钥存在storage里面,请求的时候带上这个skey,就完成了自定义登陆态。

wx.checkSession

用来校验当前用户的session_key是否有效,微信不会把session_key的有效期告知开发者,用户越频繁使用小程序,session_key有效期越长。

wx.checkSession({
	success:function(){  // 当前session_key有效
		... // 能够写咱们的业务代码
	},
	fail:function(){   // 当前session_key已过时
		wx.login()  // 从新登陆,获取新的session_key
	}
})
复制代码

当session_key过时的时候,咱们调用登陆API,更新session_key生成新的skey,并关联两者关系。

工具函数的封装

前面咱们将流程大概串了下,接下来咱们把上面的流程写成写成公用的函数

// 验证session_key状态
function checkSession(){
	return new Promise((resolve, reject) => {
		wx.checkSession({
			success:function(){
				resolve(true)
			},
			fail:function(){
				reject(false)
			}
		})
	})
}

// 登陆

function login(){
	return new Promise((resolve, reject) => {
		wx.login({
			success: (ret) => {
				wx.request({
					url:'本地服务地址',
					method: 'POST',
					data:{
						code: ret.code
					},
					success: (response) =>{
						wx.setStorageSync('skey', response.data.key)  // 将skey存在storage里面
						resolve(response.data.key)
					}
					
				})
			}
		})
		
	})
}

// 请求

function ajax(url, data, method="GET", config={}){
	let skey = wx.getStorageSync('skey') // 获取skey
	if(!skey){  // 没有skey,首次登陆
		return new Promise((resolve, reject) => {
			login()
			reject('请登陆')
		})
	} else {
		return new Promise((resolve, reject) => {
      checkSession().then( _=> {
        if (_){ // session_key有效
          wx.request({
            url,
            method: method.toLocaleUpperCase(),
            data,
            header: Object.assign({}, { skey }, config),
            success: (ret) => {
              resolve(ret.data)
            }
          })
        } else { // session_key失效
          login()
          reject('session_key失效')
        }
      })
    })

	}
}

复制代码

后端代码

后端使用koa框架,代码见文末github地址

解密

官方提供了多种编程语言的示例代码点击下载

这里咱们使用微信运动API为例

var app = getApp()  // 咱们将工具函数都放在了app的示例上面
Page({
	onLoad:function(){
		app.Util.login().then(_ => {  // 先登陆而后获取数据
      this.getrunData()
    })
	},
	getrunData(){
    wx.getWeRunData({
      success: (ret) => {
        app.Util.ajax('本地服务地址', { iv: ret.iv, data: ret.encryptedData}, 'post').then(_=>{
          console.log(_)
        }, (err)=>{
          console.log(err)
        })
      }
    })
  },

})

复制代码

返回结果以下

以上,咱们完成了小程序简单的登陆鉴权和数据解密

效果图镇楼

结尾

登陆鉴权咱们只是将用户状态放在了内存里,实际项目中确定要放在数据库中,能够拜读下大神文章,里面说到了数据库的操做。

再次致敬

本文完整代码请戳github

相关文章
相关标签/搜索