上一篇文章大概寫了一下如何搭一個微信中控服務:【thinkjs搭建微信中控服務】。html
接下來這篇,專門寫一下如何在此基礎上擴展出來一個比較好用的微信鑑權登錄的方案。前端
因爲這一段的邏輯着實有點繞,因此就單獨拿出來寫了。ios
有時候,調用方甚至能夠經過這個方案,進行多公衆號openid的之間的關聯。web
微信文檔地址:傳送門json
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
redirect_uri
地址(通常是開發者處理下一步鑑權邏輯的服務端API),而且會帶上code參數。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
具體的參數說明看微信的官方文檔就能夠了。緩存
業務調用方會有本身的登錄邏輯,只須要獲取到當前調用接口的用戶的openid,而後再進行接下來的業務邏輯便可。安全
前端調用業務接口的時候,若是服務端發現當前訪問用戶沒有登錄狀態,就會告訴前端須要鑑權,而且把須要跳轉的中控API連接響應給前端。bash
而後前端就開始往中控的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);
}
複製代碼
做用:
地址:
/open/wx/go_auth
參數:
參數名 | 必選 | 說明 |
---|---|---|
wxid | 是 | 對應配置公衆號的id,告訴中控用哪一個公衆號鑑權 |
back | 是 | 跳轉到鑑權連接以前的頁面完整url,便於鑑權完畢後重定向回以前頁面 |
serve | 是 | 調用方api回調地址,在鑑權邏輯完成後,會攜帶openid重定向回這個地址 |
描述:
我這裏默認都是靜默受權。
在這裏能夠看到代碼裏面,中控把調用方傳過來的wxid
,back
和serve
三個參數拼接到了微信API的回調連接redirect_uri
裏面。
相關代碼
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
}
複製代碼
做用:
地址:
/open/wx/login_wechat
參數:
參數名 | 必選 | 說明 |
---|---|---|
wxid | 是 | 對應配置公衆號的id,告訴中控用哪一個公衆號鑑權 |
code | 是 | 微信回傳的code |
back | 是 | 跳轉到鑑權連接以前的頁面完整url,便於鑑權完畢後重定向回以前頁面(上一步拼接的) |
serve | 是 | 調用方api回調地址,在鑑權邏輯完成後,會攜帶openid重定向回這個地址(上一步拼接的) |
描述:
這裏中控拿到code以後,去獲取openid。 獲取完以後,重定向回serve
(業務系統)地址,並把獲取到的openid
和back
做爲參數傳回去
接下來業務系統就能經過開放的回調地址(上面的serve
),來拿到如下信息:
openid
(微信ID),redirect
(上面的back
,最初用戶在前端調用接口的頁面地址)這時候就能用這個openid去處理本身的登錄邏輯,好比獲取用戶信息,緩存session保存登錄狀態之類的。
而後再重定向回back
地址,也就是用戶在鑑權以前訪問的頁面。
簡單說就是如下邏輯
雖然歷經的跳轉和重定向看起來不少,可是實際用起來,實際上是很快的,用戶基本上沒有什麼感知。
並且對於業務調用方來講,只須要提供一個回調地址便可,而後在回調裏面等着openid傳過來就好,剩下的交給中控本身去來回蹦噠吧。
須要注意的是,公衆號的後臺須要配置好如下信息。
不然是沒有權限鑑權的。