|
不知不覺已經(jīng)一個(gè)月沒有寫東西了,墮落的日子居然過的這么心(chou)安(bu)理(yao)得(lian),罪過啊。 好了,回到正文來,聊咱們的小程序。 致敬登錄大部分邏輯代碼統(tǒng)統(tǒng)來自 手把手教會(huì)你小程序登錄鑒權(quán) 登錄流程上圖是官方給出的登錄流程,我們來捋下邏輯。 1、用戶使用 wx.login 獲取臨時(shí) code ,有效期為5分鐘 2、將臨時(shí) code 傳到我們自己的后端服務(wù),調(diào)用微信的API獲取用戶的 session_key 和 openid 3、后端自定義新的密鑰并關(guān)聯(lián)返回的 session_key 和 openid ,將新的密鑰返給前端 4、前端發(fā)送請(qǐng)求的時(shí)候,帶著密鑰,后端進(jìn)行解析后返回?cái)?shù)據(jù) session_key和openid1、 session_key 會(huì)話密鑰,用來確定會(huì)話的操作的有效性和用來加密解密用戶數(shù)據(jù),服務(wù)器自己存儲(chǔ)即可,不應(yīng)該將密鑰返給前端和對(duì)話使用 2、 openid 用戶唯一標(biāo)識(shí),同樣只用于服務(wù)器,可以用來標(biāo)識(shí)用戶的唯一性 接下來,我們說下它們的獲取,通過服務(wù)端調(diào)用微信API獲取 API: https://api.weixin.qq.com/sns/jscode2session 參數(shù)如下: ![]()
// 小程序頁面
wx.login({
success:(ret)=>{
wx.request({
url: 'http://test.com', // 后端服務(wù)器
data:{
code : ret.code
}
})
}
})
后端服務(wù)我們使用 request 模塊來發(fā)送請(qǐng)求
// 后端服務(wù)
let options = {
url: 'https://api.weixin.qq.com/sns/jscode2session',
qs:{
appid: appid,
secret: secret,
js_code: code,
grant_type:'authorization_code'
}
}
// 默認(rèn)請(qǐng)求方式是get
request(options, (err, response, body) => {
if(err) return err
return body // {openid:'openid', session_key:'session_key'} 不是真正的返回 看下面的代碼
})
生成新的密鑰 skey上面我們獲取了session_key和openid,下文兩個(gè)字?jǐn)喾QkeyID,接下來我們生成一個(gè)新的密鑰返回前端并將新密鑰關(guān)聯(lián)keyID。 我們使用crypto模塊的sha1算法生成密鑰
const crypto = require('crypto')
function getShaKey(data){
return crypto.createHash('sha1').update(data, 'utf8').digest('hex')
}
上面的代碼返回我們就改成這個(gè)新的skey,前端將這個(gè)密鑰存在storage里面,請(qǐng)求的時(shí)候帶上這個(gè)skey,就完成了自定義登錄態(tài)。 wx.checkSession用來校驗(yàn)當(dāng)前用戶的session_key是否有效,微信不會(huì)把session_key的有效期告知開發(fā)者,用戶越頻繁使用小程序,session_key有效期越長(zhǎng)。
wx.checkSession({
success:function(){ // 當(dāng)前session_key有效
... // 可以寫我們的業(yè)務(wù)代碼
},
fail:function(){ // 當(dāng)前session_key已過期
wx.login() // 重新登錄,獲取新的session_key
}
})
當(dāng)session_key過期的時(shí)候,我們調(diào)用登錄API,更新session_key生成新的skey,并關(guān)聯(lián)二者關(guān)系。 工具函數(shù)的封裝前面我們將流程大概串了下,接下來我們把上面的流程寫成寫成公用的函數(shù)
// 驗(yàn)證session_key狀態(tài)
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:'本地服務(wù)地址',
method: 'POST',
data:{
code: ret.code
},
success: (response) =>{
wx.setStorageSync('skey', response.data.key) // 將skey存在storage里面
resolve(response.data.key)
}
})
}
})
})
}
// 請(qǐng)求
function ajax(url, data, method="GET", config={}){
let skey = wx.getStorageSync('skey') // 獲取skey
if(!skey){ // 沒有skey,首次登錄
return new Promise((resolve, reject) => {
login()
reject('請(qǐng)登錄')
})
} 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 地址 解密官方提供了多種編程語言的示例代碼點(diǎn)擊下載 這里我們使用微信運(yùn)動(dòng)API為例
var app = getApp() // 我們將工具函數(shù)都放在了app的示例上面
Page({
onLoad:function(){
app.Util.login().then(_ => { // 先登錄然后獲取數(shù)據(jù)
this.getrunData()
})
},
getrunData(){
wx.getWeRunData({
success: (ret) => {
app.Util.ajax('本地服務(wù)地址', { iv: ret.iv, data: ret.encryptedData}, 'post').then(_=>{
console.log(_)
}, (err)=>{
console.log(err)
})
}
})
},
})
返回結(jié)果如下 以上,我們完成了小程序簡(jiǎn)單的登錄鑒權(quán)和數(shù)據(jù)解密 結(jié)尾登錄鑒權(quán)我們只是將用戶狀態(tài)放在了內(nèi)存里,實(shí)際項(xiàng)目中肯定要放在數(shù)據(jù)庫中,可以拜讀下大神文章,里面說到了數(shù)據(jù)庫的操作。 再次致敬 |