不知不覺已經一個月沒有寫東西了,墮落的日子居然過的這麼心(chou)安(bu)理(yao)得(lian),罪過啊。
好了,回到正文來,聊我們們的小程式。
致敬
登入大部分邏輯程式碼統統來自手把手教會你小程式登入鑑權
登入流程
上圖是官方給出的登入流程,我們來捋下邏輯。
1、使用者使用wx.login
獲取臨時code
,有效期為5分鐘
2、將臨時code
傳到我們自己的後端服務,呼叫微信的API獲取使用者的session_key
和openid
3、後端自定義新的金鑰並關聯返回的session_key
和openid
,將新的金鑰返給前端
4、前端傳送請求的時候,帶著金鑰,後端進行解析後返回資料
session_key和openid
1、session_key
會話金鑰,用來確定會話的操作的有效性和用來加密解密使用者資料,伺服器自己儲存即可,不應該將金鑰返給前端和對話使用
2、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