一步步教會你微信小程序的登錄鑒權(quán)
前言
為了方便小程序應(yīng)用使用微信登錄態(tài)進行授權(quán)登錄,微信小程序提供了登錄授權(quán)的開放接口。乍一看文檔,感覺文檔上講的非常有道理,但是實現(xiàn)起來又真的是摸不著頭腦,不知道如何管理和維護登錄態(tài)。本文就來手把手的教會大家在業(yè)務(wù)里如何接入和維護微信登錄態(tài),下面話不多說了,來一起看看詳細的介紹吧。
接入流程
這里官方文檔上的流程圖已經(jīng)足夠清晰,我們直接就該圖展開詳述和補充。
首先大家看到這張圖,肯定會注意到小程序進行通信交互的不止是小程序前端和我們自己的服務(wù)端,微信第三方服務(wù)端也參與其中,那么微信服務(wù)端在其中扮演著怎樣的角色呢?我們一起來串一遍登錄鑒權(quán)的流程就明白了。
1. 調(diào)用wx.login生成code
wx.login()這個API的作用就是為當前用戶生成一個臨時的登錄憑證,這個臨時登錄憑證的有效期只有五分鐘。我們拿到這個登錄憑證后就可以進行下一步操作:獲取 openid 和 session_key
wx.login({
success: function(loginRes) {
if (loginRes.code) {
// example: 081LXytJ1Xq1Y40sg3uJ1FWntJ1LXyth
}
}
});
2. 獲取openid和session_key
我們先來介紹下openid,用過公眾號的童鞋應(yīng)該對這個標識都不陌生了,在公眾平臺里,用來標識每個用戶在訂閱號、服務(wù)號、小程序這三種不同應(yīng)用的唯一標識,也就是說每個用戶在每個應(yīng)用的openid都是不一致的,所以在小程序里,我們可以用openid來標識用戶的唯一性。
那么session_key是用來干嘛的呢?有了用戶標識,我們就需要讓該用戶進行登錄,那么 session_key 就保證了當前用戶進行會話操作的有效性,這個session_key是微信服務(wù)端給我們派發(fā)的。也就是說,我們可以用這個標識來間接地維護我們小程序用戶的登錄態(tài),那么這個session_key是怎么拿到的呢?我們需要在自己的服務(wù)端請求微信提供的第三方接口 https://api.weixin.qq.com/sns/jscode2session ,這個接口需要帶上四個參數(shù)字段:
| 參數(shù) | 值 |
|---|---|
| appid | 小程序的appid |
| secret | 小程序的secret |
| js_code | 前面調(diào)用wx.login派發(fā)的code |
| grant_type | 'authorization_code' |
從這幾個參數(shù),我們可以看出,要請求這個接口必須先調(diào)用wx.login()來獲取到用戶當前會話的code。那么為什么我們要在服務(wù)端來請求這個接口呢?其實是出于安全性的考量,如果我們在前端通過request調(diào)用此接口,就不可避免的需要將我們小程序的appid和小程序的secret暴露在外部,同時也將微信服務(wù)端下發(fā)的session_key暴露給“有心之人”,這就給我們的業(yè)務(wù)安全帶來極大的風(fēng)險。除了需要在服務(wù)端進行session_key的獲取,我們還需要注意兩點:
- session_key和微信派發(fā)的code是一一對應(yīng)的,同一code只能換取一次session_key。每次調(diào)用
wx.login(),都會下發(fā)一個新的code和對應(yīng)的session_key,為了保證用戶體驗和登錄態(tài)的有效性,開發(fā)者需要清楚用戶需要重新登錄時才去調(diào)用wx.login() - session_key是有失效性的,即便是不調(diào)用wx.login,session_key也會過期,過期時間跟用戶使用小程序的頻率成正相關(guān),但具體的時間長短開發(fā)者和用戶都是獲取不到的
function getSessionKey (code, appid, appSecret) {
var opt = {
method: 'GET',
url: 'https://api.weixin.qq.com/sns/jscode2session',
params: {
appid: appid,
secret: appSecret,
js_code: code,
grant_type: 'authorization_code'
}
};
return http(opt).then(function (response) {
var data = response.data;
if (!data.openid || !data.session_key || data.errcode) {
return {
result: -2,
errmsg: data.errmsg || '返回數(shù)據(jù)字段不完整'
}
} else {
return data
}
});
}
3. 生成3rd_session
前面說過通過 session_key 來“間接”地維護登錄態(tài),所謂間接,也就是我們需要 自己維護用戶的登錄態(tài)信息 ,這里也是考慮到安全性因素,如果直接使用微信服務(wù)端派發(fā)的session_key來作為業(yè)務(wù)方的登錄態(tài)使用,會被“有心之人”用來獲取用戶的敏感信息,比如wx.getUserInfo()這個接口呢,就需要session_key來配合解密微信用戶的敏感信息。
那么我們?nèi)绻勺约旱牡卿洃B(tài)標識呢,這里可以使用幾種常見的不可逆的哈希算法,比如md5、sha1等,將生成后的登錄態(tài)標識(這里我們統(tǒng)稱為'skey')返回給前端,并在前端維護這份登錄態(tài)標識(一般是存入storage)。而在服務(wù)端呢,我們會把生成的skey存在用戶對應(yīng)的數(shù)據(jù)表中,前端通過傳遞skey來存取用戶的信息。
可以看到這里我們使用了sha1算法來生成了一個skey:
const crypto = require('crypto');
return getSessionKey(code, appid, secret)
.then(resData => {
// 選擇加密算法生成自己的登錄態(tài)標識
const { session_key } = resData;
const skey = encryptSha1(session_key);
});
function encryptSha1(data) {
return crypto.createHash('sha1').update(data, 'utf8').digest('hex')
}
4. checkSession
前面我們將skey存入前端的storage里,每次進行用戶數(shù)據(jù)請求時會帶上skey,那么如果此時session_key過期呢?所以我們需要調(diào)用到wx.checkSession()這個API來校驗當前session_key是否已經(jīng)過期,這個API并不需要傳入任何有關(guān)session_key的信息參數(shù),而是微信小程序自己去調(diào)自己的服務(wù)來查詢用戶最近一次生成的session_key是否過期。如果當前session_key過期,就讓用戶來重新登錄,更新session_key,并將最新的skey存入用戶數(shù)據(jù)表中。
checkSession這個步驟呢,我們一般是放在小程序啟動時就校驗登錄態(tài)的邏輯處,這里貼個校驗登錄態(tài)的流程圖:
下面代碼即校驗登錄態(tài)的簡單流程:
let loginFlag = wx.getStorageSync('skey');
if (loginFlag) {
// 檢查 session_key 是否過期
wx.checkSession({
// session_key 有效(未過期)
success: function() {
// 業(yè)務(wù)邏輯處理
},
// session_key 過期
fail: function() {
// session_key過期,重新登錄
doLogin();
}
});
) else {
// 無skey,作為首次登錄
doLogin();
}
5. 支持emoji表情存儲
如果需要將用戶微信名存入數(shù)據(jù)表中,那么就確認數(shù)據(jù)表及數(shù)據(jù)列的編碼格式。因為用戶微信名可能會包含emoji圖標,而常用的UTF8編碼只支持1-3個字節(jié),emoji圖標剛好是4個字節(jié)的編碼進行存儲。
這里有兩種方式(以mysql為例):
1.設(shè)置存儲字符集
在mysql5.5.3版本后,支持將數(shù)據(jù)庫及數(shù)據(jù)表和數(shù)據(jù)列的字符集設(shè)置為 utf8mb4 ,因此可在 /etc/my.cnf 設(shè)置默認字符集編碼及服務(wù)端編碼格式
// my.cnf [client] default-character-set=utf8mb4 [mysql] default-character-set=utf8mb4 [mysqld] character-set-client-handshake = FALSE character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci
設(shè)置完默認字符集編碼及服務(wù)端字符集編碼,如果是對已經(jīng)存在的表和字段進行編碼轉(zhuǎn)換,需要執(zhí)行下面幾個步驟:
設(shè)置數(shù)據(jù)庫字符集為 utf8mb4
ALTER DATABASE 數(shù)據(jù)庫名稱 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
設(shè)置數(shù)據(jù)表字符集為 utf8mb4
ALTER TABLE 數(shù)據(jù)表名稱 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
設(shè)置數(shù)據(jù)列字段字符集為 utf8mb4
ALTER TABLE 數(shù)據(jù)表名稱 CHANGE 字段列名稱 VARCHAR(n) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
這里的 COLLATE 指的是排序字符集,也就是用來對存儲的字符進行排序和比較的, utf8mb4 常用的collation有兩種: utf8mb4_unicode_ci 和 utf8mb4_general_ci ,一般建議使用 utf8mb4_unicode_ci ,因為它是基于標準的 Unicode Collation Algorithm(UCA) 來排序的,可以在各種語言進行精確排序。這兩種排序方式的具體區(qū)別可以參考:
2.通過使用sequelize對emoji字符進行編碼入庫,使用時再進行解碼
這里是sequelize的配置,可參考 Sequelize文檔
{
dialect: 'mysql', // 數(shù)據(jù)庫類型
dialectOptions: {
charset: 'utf8mb4',
collate: "utf8mb4_unicode_ci"
},
}
最后
前面講了微信小程序如何接入微信登錄態(tài)標識的詳細流程,那么如何獲取小程序中的用戶數(shù)據(jù)以及對用戶敏感數(shù)據(jù)進行解密,并保證用戶數(shù)據(jù)的完整性,我將在下一篇文章給大家做一個詳細地介紹。
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
使用JavaScriptCore實現(xiàn)OC和JS交互詳解
JavaScriptCore是webkit的一個重要組成部分,主要是對JS進行解析和提供執(zhí)行環(huán)境。下面這篇文章主要給大家介紹了使用JavaScriptCore實現(xiàn)OC和JS交互的相關(guān)資料,文中介紹的非常詳細,需要的朋友可以參考學(xué)習(xí),下面來一起看看吧。2017-03-03
js實現(xiàn)網(wǎng)頁右上角滑出會自動消失大幅廣告的方法
這篇文章主要介紹了js實現(xiàn)網(wǎng)頁右上角滑出會自動消失大幅廣告的方法,是javascript廣告特效的典型應(yīng)用,非常具有實用價值,需要的朋友可以參考下2015-02-02
基于Node.js的JavaScript項目構(gòu)建工具gulp的使用教程
也許你使用過grunt,那么這里來安利gulp的話就更加不會陌生了,下面我們就來看一下基于Node.js的JavaScript項目構(gòu)建工具gulp的使用教程2016-05-05
基于Marquee.js插件實現(xiàn)的跑馬燈效果示例
這篇文章主要介紹了基于Marquee.js插件實現(xiàn)的跑馬燈效果,結(jié)合實例形式給出了Marquee.js插件的定義及具體使用方法,需要的朋友可以參考下2017-01-01
解決前端使用xlsx.js工具讀取excel遇到時間日期少43秒問題
這篇文章主要給大家介紹了關(guān)于如何解決前端使用xlsx.js工具讀取excel遇到時間日期少43秒問題的相關(guān)資料,xlsx.js是一種前端庫,它可以使您使用JavaScript讀取、解析和導(dǎo)出電子表格文件,如Microsoft Excel,需要的朋友可以參考下2024-03-03
利用javascript實現(xiàn)禁用網(wǎng)頁上所有文本框,下拉菜單,多行文本域
這篇文章主要介紹了利用javascript實現(xiàn)禁用網(wǎng)頁上所有文本框,下拉菜單,多行文本域。需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12

