小程序的登陸和數據解密全解析

不知不覺已經一個月沒有寫東西了,墮落的日子竟然過的這麼心(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

相關文章
相關標籤/搜索