「LeanCloud Web 應用開發實踐」系列直播及文章分享持續進行中。
每週二週四晚上 8 點開始,時長預計 45 分鐘。在 「leanCloud通信」 微信公衆號回覆 「公開課」 便可獲取直播連接。javascript
點擊查看完整公開課視頻css
OAuth(開放受權)是一個開放標準,容許用戶讓第三方應用訪問該用戶在某一網站上存儲的私密的資源(如照片,視頻,聯繫人列表),而無需將用戶名和密碼提供給第三方應用。維基百科html
以 Ticket 爲例,轉換下說法就是:java
容許用戶讓 Ticket 應用訪問該用戶在 LeanCloud 上存儲的私密資源(如帳號,應用列表),而無需將用戶名和密碼提供給 Ticket。git
clientId
和 clientSecret
。1.用戶訪問 Ticket 應用,當 Ticket 須要用戶在 LeanCloud 上的信息時(好比 Ticket 想使用用戶在 LeanCloud 上的信息來註冊本身的網站),OAuth 受權過程開始。github
2.Ticket 服務端拼接 LeanCloud 的受權地址給用戶,並附帶一些信息,包括:express
3.用戶瀏覽器根據剛纔的響應,跳轉到 LeanCloud 的受權頁面。LeanCloud 受權頁面會展示一些信息:api
clientId
。scope
。用戶根據這些信息判斷是否贊成受權:若是取消,OAuth 受權流程終止;若是贊成,LeanCloud 會生成一個重定向請求到 Ticket,並在請求上附帶一個屬性 code
。該 code
在 LeanCloud 內部會記錄,而且和 Ticket 應用,還有當前受權用戶關聯。至於調轉到 Ticket 的哪一個地址,由剛纔 Ticket 重定向過來時候的 callbackUrl
決定。瀏覽器
code
信息。Ticket 服務端會向 LeanCloud 發起請求,獲取用戶的 accessToken
信息,請求會攜帶一些參數:clientId:準備工做裏面 LeanCloud 辦法給 Ticket 的 clientId
。bash
clientSecret:準備工做裏面 LeanCloud 辦法給 Ticket 的 clientSecret
。
LeanCloud 根據參數信息就能肯定是哪一個應用要獲取哪一個用戶的 accessToken
,若是全部信息確認無誤,則返回 accessToken
。
clientSecret
是私密的,不能泄漏,建議不要直接配置在項目代碼中。若是部署在雲引擎,建議使用雲引擎的環境變量來保存這些數據。雲引擎環境變量設置方式: LeanCloud 控制檯 -> 雲引擎 -> 設置 -> 自定義環境變量,增長鬚要的變量名和變量值,點保存,下次部署時生效。至此,OAuth 受權結束。
相關代碼介紹 25:26
本期視頻使用的代碼地址:github.com/leancloud/t…
版本:664259e
可使用下面的命令獲取:
git clone https://github.com/leancloud/ticket.git
cd ticket
git checkout 664259e複製代碼
整個流程涉及到的代碼部分:
<div className={css.wrap}>
<h1 className='font-logo'>歡迎回來</h1>
<hr />
<p>目前只支持經過 {ORG_NAME} OAuth 受權進行登陸</p>
<a href='/oauth/login' className='btn btn-primary'>前往 {ORG_NAME} 受權頁</a>
</div>複製代碼
可見,當用戶點擊「前往 LeanCloud 受權頁」按鈕是,將請求 GET /oauth/login 路由。
...
router.use('/oauth/login', require('./oauth').login(loginCallbackUrl))
...複製代碼
路由方法定義在 api/oauth.js 的 login 方法中:
exports.login = (callbackUrl) => {
return (req, res) => {
const loginUrl = serverDomain + '/1.1/authorize?' +
qs.stringify({
client_id: config.oauthKey,
response_type: 'code',
redirect_uri: callbackUrl,
scope: oauthScope,
})
res.redirect(loginUrl)
}
}複製代碼
該方法接受一個 callbackUrl
參數,返回一個 express 的路由方法(即接收 request
和 response
爲參數的方法)。在這個路由方法中拼接了 LeanCloud 受權頁的請求,而後向客戶端回覆一個 302 響應(由 res.redirect()
方法實現)。
...
router.use(loginCallbackPath, require('./oauth').loginCallback(loginCallbackUrl))
...複製代碼
路由的 具體實現:
exports.loginCallback = (callbackUrl) => {
return (req, res) => {
getAccessToken(req.query.code, callbackUrl).then((accessToken) => {
accessToken.uid = '' + accessToken.uid
return AV.User.signUpOrlogInWithAuthData(accessToken, 'leancloud')
}).then((user) => {
if (_.isEqual(user.createdAt, user.updatedAt)) {
// 第一次登陸,從 LeanCloud 初始化用戶信息
return initUserInfo(user)
}
return user
}).then((user) => {
res.redirect('/login?token=' + user._sessionToken)
})
}
}複製代碼
可見路由的實現中:
code
信息到 LeanCloud 網站獲取該用戶的 accessToken
(詳見 getAccessToken)。_User
表的 authData
列會保存用戶在對應平臺的受權信息。username
和 email
信息來設置用戶在 Ticket 裏的信息(詳見 initUserInfo1)。sessionToken
做爲 queryString
,進行客戶端登陸(res.redirect('/login?token=' + user._sessionToken)
)。sessionToken
進行客戶端登陸,代碼 modules/Login.jsconst query = nextProps.location.query
if (query.token) {
return AV.User.become(query.token)
...
}複製代碼
至此,OAuth 受權,以及服務端建立(或登陸)用戶,以及客戶端同步登陸過程所有結束。
若是須要用戶在 LeanCloud 上的其餘信息,Ticket 服務端可使用用戶的 accessToken
(_User
表的authData
屬性中)來獲取,能夠參考這些方法:
咱們只介紹了 OAuth 的最基本流程,以及最必要的請求參數,至於 OAuth 受權爲什麼須要這些步驟,以及每一步的某些參數爲什麼要這樣設計,建議你們參考更詳細的文檔或協議說明。
若是本身的應用要申請別的網站 OAuth 受權(好比 QQ),能夠查看對應網站提供的 OAuth 相關文檔。
若是要本身實現 OAuth Server,不須要本身實現,各個語言都有相關的庫,能極大的下降實現成本。