這里對接的是自己公司的 open 平臺,但是會開放到外部供其它公司調用。所以授權服務器是 open 平臺,下面授權服務器將統一稱為平臺服務器。
使用的是 Auth2.0 的標準(授權碼模式),和微信一致,所以其實本質上是通用的,Auth2.0 介紹可以直接看這里,這篇已經講得很通俗易懂,所以本文不再贅述。
項目是采取前后端分離的方式,前端主要是 vue+node,node 作為中間件,后端是 golang。
以下的代碼都是代碼段,把最關鍵的部分抽出來了,雖然不是完整的代碼,但是已經足夠能說明了。
現在講一下步驟(每步之前都先介紹參數含義):
第一步:申請權限
別誤會,這里的申請權限并不是直接申請就能直接請求用戶授權信息了,這里是為了去平臺申請一個唯一的ID(client_id)和秘鑰(client_secret)以及授權回調域名(同微信端的 AppID 和 appsecret 以及授權回調域名),回調域名要在平臺的白名單當中,這個回調域名通常是自己的應用的域名。
第二步:獲取 code
拿到 client_id 后就可以去獲取 code 了,先進行參數說明
client_id:客戶端 ID (等同于微信中的 AppID,也就是自己的應用在對接平臺中的唯一 ID)
redirect_uri: 重定向地址,即獲取到 code 以后要跳轉的地址,該地址必須在平臺的白名單中,需要用 encodeURIComponent 進行編碼。
scope:授權范圍,也就是用戶允許平臺服務器授權給自己應用的范圍(同微信 scope,如果需要被授權獲取到用戶信息則設置為
snsapi_userinfo,每個平臺設置的應該都不一樣)。
response_type: 返回類型,固定為 code
state:可以帶上一些狀態,平臺服務器到時候會原樣返回
我們需要根據以上多個參數獲取 code(授權碼),具體需要哪些參數要看不同的平臺的規定,但是基本上會包含上述五個,,其中 client_id 是對接的平臺為自己的應用分配的。redirect_uri 不是隨便寫的,而是應該要能跳轉到的地址可以發起下一步的請求,并且可以帶上額外的參數,具體后面再說。
現在假設參數為
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)
}
可以設置任意 api,指定執行該 connect 的函數以發起請求。比如:
import Router from 'koa-router'
import connect from './connect'
router.get('/open/connect', connect)
在請求了 /open/connect 這個 api 后,會調用 connect 函數去跳轉獲取 code,如果成功的話,平臺服務器則會返回你給定的重定向地址:
http://abc.demo.com/callback?code=zzaabb&state=abcabc
拿到 code 后第一步就算結束了。
第三步:獲取 access_token
剛才第一步結束時,平臺的服務器直接返回了鏈接為 http://abc.demo.com/callback?code=zzaabb&state=abcabc,其中 http://abc.demo.com 為自己應用的域名,callback 為路由地址,對應的函數將要執行下一步。
這里可以用 node 去處理,也可以用 golang 處理。先講一下 node 處理的方式。
grant_type: 固定為 authorization_code
client_id:客戶端 ID
client_secret:客戶端被平臺分配的秘鑰(等同于微信中的 secret 參數名,值為公眾號的appsecret)
code:剛剛獲取的授權碼,通常使用一次就會失效
代碼如下:
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 端直接對平臺服務器發起了請,獲取到了 access_token 和 expires_in,這個 expires_in 是 access_token 有效時間。
第四步
獲取到了 access_token 以后,授權才結束。這時才能用 access_token 去正式請求平臺服務器獲取用戶信息。這個 access_token 可以存儲到 session 當中,比如 redis 里。這樣獲取用戶信息的時候就不需要每次都重新去獲取授權,用戶體驗也不好。但是這里需要特別注意一個地方,就是任意用戶都能發起請求去直接請求到任意用戶的信息,所以這里如果要存儲到 redis 的話,需要對前端發起的請求進行校驗,校驗通過以后才能去數據庫拿到 access_token。但是因為這里的 node 不作為真正的后端去使用,所以以下只是演示,真正使用 golang 做的對接后面會寫到。
access_token:調用用戶信息的憑證,只有拿到這個參數才能去獲取到用戶信息。
下面根據拿到的 access_token 獲取用戶信息:
import axios from 'axios'
exports.getUser = async function(ctx) {
let user = await axios.get(`https://m.open.com/user`, {
params: {
access_token,
},
})
}
通常一篇文章特別長,看下來比較容易沒耐心,所以 golang 對接的步驟將在下一篇中再介紹。
今天就暫時到這里把~