這里對(duì)接的是自己公司的 open 平臺(tái),但是會(huì)開放到外部供其它公司調(diào)用劫哼。所以授權(quán)服務(wù)器是 open 平臺(tái)皂吮,下面授權(quán)服務(wù)器將統(tǒng)一稱為平臺(tái)服務(wù)器。
使用的是 Auth2.0 的標(biāo)準(zhǔn)(授權(quán)碼模式)脑奠,和微信一致,所以其實(shí)本質(zhì)上是通用的幅慌,Auth2.0 介紹可以直接看這里宋欺,這篇已經(jīng)講得很通俗易懂,所以本文不再贅述胰伍。
項(xiàng)目是采取前后端分離的方式齿诞,前端主要是 vue+node,node 作為中間件骂租,后端是 golang祷杈。
以下的代碼都是代碼段,把最關(guān)鍵的部分抽出來了渗饮,雖然不是完整的代碼但汞,但是已經(jīng)足夠能說明了宿刮。
現(xiàn)在講一下步驟(每步之前都先介紹參數(shù)含義):
第一步:申請(qǐng)權(quán)限
別誤會(huì),這里的申請(qǐng)權(quán)限并不是直接申請(qǐng)就能直接請(qǐng)求用戶授權(quán)信息了私蕾,這里是為了去平臺(tái)申請(qǐng)一個(gè)唯一的ID(client_id)和秘鑰(client_secret)以及授權(quán)回調(diào)域名(同微信端的 AppID 和 appsecret 以及授權(quán)回調(diào)域名)僵缺,回調(diào)域名要在平臺(tái)的白名單當(dāng)中,這個(gè)回調(diào)域名通常是自己的應(yīng)用的域名踩叭。
第二步:獲取 code
拿到 client_id 后就可以去獲取 code 了磕潮,先進(jìn)行參數(shù)說明
client_id:客戶端 ID (等同于微信中的 AppID,也就是自己的應(yīng)用在對(duì)接平臺(tái)中的唯一 ID)
redirect_uri: 重定向地址容贝,即獲取到 code 以后要跳轉(zhuǎn)的地址自脯,該地址必須在平臺(tái)的白名單中,需要用 encodeURIComponent 進(jìn)行編碼嗤疯。
scope:授權(quán)范圍冤今,也就是用戶允許平臺(tái)服務(wù)器授權(quán)給自己應(yīng)用的范圍(同微信 scope,如果需要被授權(quán)獲取到用戶信息則設(shè)置為
snsapi_userinfo茂缚,每個(gè)平臺(tái)設(shè)置的應(yīng)該都不一樣)戏罢。
response_type: 返回類型,固定為 code
state:可以帶上一些狀態(tài)脚囊,平臺(tái)服務(wù)器到時(shí)候會(huì)原樣返回
我們需要根據(jù)以上多個(gè)參數(shù)獲取 code(授權(quán)碼)龟糕,具體需要哪些參數(shù)要看不同的平臺(tái)的規(guī)定,但是基本上會(huì)包含上述五個(gè)悔耘,讲岁,其中 client_id 是對(duì)接的平臺(tái)為自己的應(yīng)用分配的。redirect_uri 不是隨便寫的衬以,而是應(yīng)該要能跳轉(zhuǎn)到的地址可以發(fā)起下一步的請(qǐng)求缓艳,并且可以帶上額外的參數(shù),具體后面再說看峻。
現(xiàn)在假設(shè)參數(shù)為
client_id = 'app01',
redirect_uri = 'http://abc.demo.com/callback',
scope = 'userinfo',
response_type = 'code',
state = 'abcabc',
import querystring from 'querystring'
exports.connect = async function(ctx) {
let url = https://m.open.com/oauth2/authorize'
let info= {
client_id: 'ABC',
redirect_uri: 'http://abc.demo.com/callback', // 注意這里的 http:// 不可以省
scope: 'userinfo',
response_type: 'code',
state: 'abcabc',
}
const finalUrl = url + '?' + querystring.stringify(info)
await ctx.redirect(finalUrl)
}
可以設(shè)置任意 api阶淘,指定執(zhí)行該 connect 的函數(shù)以發(fā)起請(qǐng)求。比如:
import Router from 'koa-router'
import connect from './connect'
router.get('/open/connect', connect)
在請(qǐng)求了 /open/connect 這個(gè) api 后互妓,會(huì)調(diào)用 connect 函數(shù)去跳轉(zhuǎn)獲取 code溪窒,如果成功的話,平臺(tái)服務(wù)器則會(huì)返回你給定的重定向地址:
http://abc.demo.com/callback?code=zzaabb&state=abcabc
拿到 code 后第一步就算結(jié)束了冯勉。
第三步:獲取 access_token
剛才第一步結(jié)束時(shí)澈蚌,平臺(tái)的服務(wù)器直接返回了鏈接為 http://abc.demo.com/callback?code=zzaabb&state=abcabc,其中 http://abc.demo.com 為自己應(yīng)用的域名灼狰,callback 為路由地址宛瞄,對(duì)應(yīng)的函數(shù)將要執(zhí)行下一步。
這里可以用 node 去處理交胚,也可以用 golang 處理份汗。先講一下 node 處理的方式伐厌。
grant_type: 固定為 authorization_code
client_id:客戶端 ID
client_secret:客戶端被平臺(tái)分配的秘鑰(等同于微信中的 secret 參數(shù)名,值為公眾號(hào)的appsecret)
code:剛剛獲取的授權(quán)碼裸影,通常使用一次就會(huì)失效
代碼如下:
import axios from 'axios'
exports.callback = async function(ctx) {
let { code } = ctx.query
let { access_token, expires_in } = await
axios.post(`https://m.open.com/oauth2/access_token`, {
grant_type: 'authorization_code',
client_id: 'app01',
client_secret: 'imsecret01',
code: 'zzaabb'
});
}
可以看到這里是 node 端直接對(duì)平臺(tái)服務(wù)器發(fā)起了請(qǐng),獲取到了 access_token 和 expires_in军熏,這個(gè) expires_in 是 access_token 有效時(shí)間轩猩。
第四步
獲取到了 access_token 以后,授權(quán)才結(jié)束荡澎。這時(shí)才能用 access_token 去正式請(qǐng)求平臺(tái)服務(wù)器獲取用戶信息均践。這個(gè) access_token 可以存儲(chǔ)到 session 當(dāng)中,比如 redis 里摩幔。這樣獲取用戶信息的時(shí)候就不需要每次都重新去獲取授權(quán)彤委,用戶體驗(yàn)也不好。但是這里需要特別注意一個(gè)地方或衡,就是任意用戶都能發(fā)起請(qǐng)求去直接請(qǐng)求到任意用戶的信息焦影,所以這里如果要存儲(chǔ)到 redis 的話,需要對(duì)前端發(fā)起的請(qǐng)求進(jìn)行校驗(yàn)封断,校驗(yàn)通過以后才能去數(shù)據(jù)庫拿到 access_token斯辰。但是因?yàn)檫@里的 node 不作為真正的后端去使用,所以以下只是演示坡疼,真正使用 golang 做的對(duì)接后面會(huì)寫到彬呻。
access_token:調(diào)用用戶信息的憑證,只有拿到這個(gè)參數(shù)才能去獲取到用戶信息柄瑰。
下面根據(jù)拿到的 access_token 獲取用戶信息:
import axios from 'axios'
exports.getUser = async function(ctx) {
let user = await axios.get(`https://m.open.com/user`, {
params: {
access_token,
},
})
}
通常一篇文章特別長(zhǎng)闸氮,看下來比較容易沒耐心,所以 golang 對(duì)接的步驟將在下一篇中再介紹教沾。
今天就暫時(shí)到這里把~