thinkjs微信中控之微信鑑權登錄

前言

上一篇文章大概寫了一下如何搭一個微信中控服務:【thinkjs搭建微信中控服務】html

接下來這篇,專門寫一下如何在此基礎上擴展出來一個比較好用的微信鑑權登錄的方案。前端

因爲這一段的邏輯着實有點繞,因此就單獨拿出來寫了。ios

有時候,調用方甚至能夠經過這個方案,進行多公衆號openid的之間的關聯。web

官方說明

開發文檔

微信文檔地址:傳送門json

鑑權邏輯

  1. 前端跳轉到如下url,重定向或者代碼跳轉均可以:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
  2. 彈出是否贊成受權的框,用戶贊成受權(若是是靜默受權,就不會彈出贊成框),而後頁面會重定向到上面連接的redirect_uri地址(通常是開發者處理下一步鑑權邏輯的服務端API),而且會帶上code參數。
  3. 服務端拿到code以後,調用如下api來獲取網頁受權的access_token和用戶的openid:https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

拿到openid以後,理論上鑑權的邏輯就算完成了。axios

開發者能夠繼續用openid和access_token去獲取用戶信息;或者進行一些其餘的業務流程。api

具體的參數說明看微信的官方文檔就能夠了。緩存

中控邏輯

第一步:頁面跳轉至中控API

業務調用方會有本身的登錄邏輯,只須要獲取到當前調用接口的用戶的openid,而後再進行接下來的業務邏輯便可。安全

前端調用業務接口的時候,若是服務端發現當前訪問用戶沒有登錄狀態,就會告訴前端須要鑑權,而且把須要跳轉的中控API連接響應給前端。bash

而後前端就開始往中控的API連接跳轉。

第二步:中控重定向到微信API

相關代碼

// 接口 - 鑑權獲取code
async go_authAction() {
    let that = this;
    let {back, serve = ''} = that.get();
    if (think.isEmpty(back)) {
        return that.json({code: 1, msg: '參數不正確'})
    }
    let newBack = encodeURIComponent(back);
    let redirectUri = `${baseHost}/api/open/wx/login_wechat?${encodeURIComponent(`back=${newBack}&wxid=${that.wxConfig.id}&serve=${serve}`)}`;
    let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${that.wxConfig.appid}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`
    that.redirect(url);
}
複製代碼

做用:

  • 鑑權獲取code

地址:

  • baseHost + /open/wx/go_auth

參數:

參數名 必選 說明
wxid 對應配置公衆號的id,告訴中控用哪一個公衆號鑑權
back 跳轉到鑑權連接以前的頁面完整url,便於鑑權完畢後重定向回以前頁面
serve 調用方api回調地址,在鑑權邏輯完成後,會攜帶openid重定向回這個地址

描述:

我這裏默認都是靜默受權。

在這裏能夠看到代碼裏面,中控把調用方傳過來的wxid,backserve三個參數拼接到了微信API的回調連接redirect_uri裏面。

第三步:微信回調中控API

相關代碼

async login_wechatAction() {
    let that = this;
    let {code, back, serve = ''} = that.get();
    if (think.isEmpty(code) || think.isEmpty(back)) {
        return that.json({code: 1, msg: '參數不正確'})
    }
    let newBack = encodeURIComponent(back);
    let apiWxController = that.controller('private/wx');
    let openid = await that._getOpenIdByAuthCode(that.wxConfig.id, code);
    let backUrl = `${serve}?wxid=${that.wxConfig.id}&openid=${openid}&redirect=${newBack}`;
    that.redirect(backUrl);
}

_getOpenIdByAuthCode(wxid, code){
    let that = this;
    let {appid, secret} = await that.controller('common').getWxConfigById(wxid);
    let {data} = await axios({
        method: 'get',
        url: `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${appid}&secret=${secret}&code=${code}&grant_type=authorization_code`
    })
    return data.openid
}
複製代碼

做用:

  • 經過微信回調傳回來的code,獲取openid

地址:

  • baseHost + /open/wx/login_wechat

參數:

參數名 必選 說明
wxid 對應配置公衆號的id,告訴中控用哪一個公衆號鑑權
code 微信回傳的code
back 跳轉到鑑權連接以前的頁面完整url,便於鑑權完畢後重定向回以前頁面(上一步拼接的)
serve 調用方api回調地址,在鑑權邏輯完成後,會攜帶openid重定向回這個地址(上一步拼接的)

描述:

這裏中控拿到code以後,去獲取openid。 獲取完以後,重定向回serve(業務系統)地址,並把獲取到的openidback做爲參數傳回去

第四步:業務系統自行處理

接下來業務系統就能經過開放的回調地址(上面的serve),來拿到如下信息:

  • openid(微信ID),
  • redirect(上面的back,最初用戶在前端調用接口的頁面地址)

這時候就能用這個openid去處理本身的登錄邏輯,好比獲取用戶信息,緩存session保存登錄狀態之類的。

而後再重定向回back地址,也就是用戶在鑑權以前訪問的頁面。

鑑權結束

簡單說就是如下邏輯

  • 前端 調用 業務接口 發現沒有登錄狀態,告訴前端往中控跳!
  • 前端 跳轉至 中控API 拼接接下來要回調的參數
  • 中控 重定向至 微信API 獲取code
  • 微信 重定向至 中控API 獲取openid
  • 中控 重定向回 業務回調API 拿到openid,保存用戶登錄狀態
  • 業務 重定向回 前端
  • 前端 調用 業務接口 發現有登錄狀態了,完事兒

雖然歷經的跳轉和重定向看起來不少,可是實際用起來,實際上是很快的,用戶基本上沒有什麼感知。

並且對於業務調用方來講,只須要提供一個回調地址便可,而後在回調裏面等着openid傳過來就好,剩下的交給中控本身去來回蹦噠吧。

結尾

須要注意的是,公衆號的後臺須要配置好如下信息。

  • JS接口安全域名:就是前端的訪問域名。
  • 網頁受權域名:中控API域名。
  • ip白名單:中控的ip地址。

不然是沒有權限鑑權的。

相關文章
相關標籤/搜索