提供用戶登陸以及維護用戶的登陸狀態,是一個擁有用戶系統的軟件應用廣泛須要作的事情。像微信這樣的一個社交平臺,若是作一個小程序應用,咱們可能不多會去作一個徹底脫離和捨棄鏈接用戶信息的純工具軟件。redis
讓用戶登陸,標識用戶和獲取用戶信息,以用戶爲核心提供服務,是大部分小程序都會作的事情。咱們今天就來了解下在小程序中,如何作用戶登陸,以及如何去維護這個登陸後的會話(Session)狀態。json
在微信小程序中,咱們大體會涉及到如下三類登陸方式:小程序
第一和第二種方式是目前Web應用中最多見的兩種方式,在微信小程序中一樣可使用,可是須要值的注意的是,小程序中沒有Cookie
的機制,因此在使用這2種方式前,請確認大家或第三方的API是否須要依賴Cookie
;還有小程序中也不支持HTML頁面,那些須要使用頁面重定向來進行登陸的第三方API就須要改造,或不能用了。微信小程序
咱們今天主要來討論一下第三種方式,即如何使用微信帳號進行登陸,由於這種方式和微信平臺結合最緊密,用戶體驗比較好。api
引用小程序官方文檔的登陸流程圖,整個登陸流程基本以下圖所示:瀏覽器
登陸流程圖安全
該圖中,「小程序」指的就是咱們使用小程序框架寫的代碼部分,「第三方服務器」通常就是咱們本身的後臺服務程序,「微信服務器」是微信官方的API服務器。服務器
下面咱們來逐步分解一下這個流程圖。微信
登陸憑證(code)
在小程序中登陸的第一步,就是先獲取登陸憑證。咱們可使用wx.login()方法並獲得一個登陸憑證。cookie
咱們能夠在小程序的App代碼中發起登陸憑證請求,也能夠在其餘任何Page頁面代碼中發起登陸憑證請求,主要根據你小程序的實際須要。
App({ onLaunch: function() { wx.login({ success: function(res) { var code = res.code; if (code) { console.log('獲取用戶登陸憑證:' + code); } else { console.log('獲取用戶登陸態失敗:' + res.errMsg); } } }); } })
惟一標識(openid)
和會話密鑰(session_key)
首先,咱們使用wx.request()方法,請求咱們本身實現的一個後臺API,並將登陸憑證(code)攜帶過去,例如在咱們前面代碼的基礎上增長:
App({ onLaunch: function() { wx.login({ success: function(res) { var code = res.code; if (code) { console.log('獲取用戶登陸憑證:' + code); // --------- 發送憑證 ------------------ wx.request({ url: 'https://www.my-domain.com/wx/onlogin', data: { code: code } }) // ------------------------------------ } else { console.log('獲取用戶登陸態失敗:' + res.errMsg); } } }); } })
你的後臺服務(/wx/onlogin)接着須要使用這個傳遞過來的登陸憑證,去調用微信接口換取openid和session_key,接口地址格式以下所示:
https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
這裏是我使用了Node.js Express構建的後臺服務的代碼,僅供參考:
router.get('/wx/onlogin', function (req, res, next) { let code = req.query.code request.get({ uri: 'https://api.weixin.qq.com/sns/jscode2session', json: true, qs: { grant_type: 'authorization_code', appid: '你小程序的APPID', secret: '你小程序的SECRET', js_code: code } }, (err, response, data) => { if (response.statusCode === 200) { console.log("[openid]", data.openid) console.log("[session_key]", data.session_key) //TODO: 生成一個惟一字符串sessionid做爲鍵,將openid和session_key做爲值,存入redis,超時時間設置爲2小時 //僞代碼: redisStore.set(sessionid, openid + session_key, 7200) res.json({ sessionid: sessionid }) } else { console.log("[error]", err) res.json(err) } }) })
這段後臺代碼成功執行的話,就能夠獲得openid和session_key。這個信息就是當前微信帳戶在微信服務器那邊的登陸態了。
可是,爲了安全方面的緣由,請不要直接使用這些信息做爲你小程序的用戶標識和session標識回傳到小程序客戶端中去,咱們應該在服務器端作一層本身的session,將這個微信帳號登陸態生成一個session id並維護在咱們本身的session機制中,而後把這個session id派發到小程序客戶端做爲session標識來使用。
關於如何在服務器端作這個session機制,咱們如今通常採用鍵值對存儲工具來作,好比redis。咱們爲每一個session生成一個惟一的字符串做爲鍵,而後能夠將session_key和openid做爲值,存入redis中,爲了安全,存入的時候還應設置一個超時的時間。
sessionid
開發Web應用的時候,在客戶端(瀏覽器)中,咱們一般將session id存放在cookie中,可是小程序沒有cookie機制,因此不能採用cookie了,可是小程序有本地的storage,因此咱們可使用storage來保存sessionid,以供後續的後臺API調用所使用。
在以後,調用那些須要登陸後纔有權限的訪問的後臺服務時,你能夠將保存在storage中的sessionid取出並攜帶在請求中(能夠放在header中攜帶,也能夠放在querystring中,或是放在body中,根據你本身的須要來使用),傳遞到後臺服務,後臺代碼中獲取到該sessionid後,從redis中查找是否有該sessionid存在,存在的話,即確認該session是有效的,繼續後續的代碼執行,不然進行錯誤處理。
這是一個須要session驗證的後臺服務示例,個人sessionid是放在header中傳遞的,因此在這個示例中,是從請求的header中獲取sessionid:
router.get('/wx/products/list', function (req, res, next) { let sessionid = req.header("sessionid") let sessionVal = redisStore.get(sessionid) if (sessionVal) { // 執行其餘業務代碼 } else { // 執行錯誤處理 } })
好了,經過微信帳號進行小程序登陸和狀態維護的簡單流程就是這樣,瞭解這些知識點以後,再基於此進行後續的開發就會變得更容易了。
文章來源:http://www.jianshu.com/p/c5f6c98b2685
做者:一斤代碼