OAuth2 快速入門
點擊上方藍色字體,選擇“標(biāo)星公眾號”
優(yōu)質(zhì)文章,第一時間送達
? 作者?|??Rekent
來源 |? urlify.cn/yqqQNj
1 OAuth簡述
OAuth 2.0 是一個授權(quán)協(xié)議,它允許軟件應(yīng)用代表(而不是充當(dāng))資源擁有者去訪問資源擁有者的資源。應(yīng)用向資源擁有者請求授權(quán),然后取得令牌(token),并用它來訪問資源,并且資源擁有者不用向應(yīng)用提供用戶名和密碼等敏感數(shù)據(jù)。
2 OAuth角色
OAuth整個授權(quán)過程中定義了4種角色:
客戶端(Cilent):代表資源擁有者訪問受保護資源的軟件,它使用OAuth 來獲取訪問權(quán)限;
資源擁有者(Resource Owner):是有權(quán)將訪問權(quán)限授權(quán)給客戶端的主體,在大多數(shù)情況下,資源擁有者是一個人,他使用客戶端軟件訪問受他控制的資源;
資源服務(wù)器(Resource Server):資源服務(wù)器能夠通過HTTP 服務(wù)器進行訪問,在訪問時需要OAuth 訪問令牌。受保護資源需要驗證收到的令牌,并決定是否響應(yīng)以及如何響應(yīng)請求;
授權(quán)服務(wù)器(Authorization Server):一個HTTP 服務(wù)器,它在OAuth 系統(tǒng)中充當(dāng)中央組件。授權(quán)服務(wù)器對資源擁有者和客戶端進行身份認(rèn)證,讓資源擁有者向客戶端授權(quán)、為客戶端頒發(fā)令牌。某些授權(quán)服務(wù)器還會提供額外的功能,例如令牌內(nèi)省、記憶授權(quán)決策;
假設(shè)你使用了一個照片云存儲服務(wù)和一個云打印服務(wù),并且想使用云打印服務(wù)來打印存放在云存儲服務(wù)上的照片。很幸運,這兩個服務(wù)能夠使用API 來通信。這很好,但兩個服務(wù)由不同的公司提供,這意味著你在云存儲服務(wù)上的賬戶和在云打印服務(wù)上的賬戶沒有關(guān)聯(lián)。使用OAuth 可以解決這個問題:授權(quán)云打印服務(wù)訪問照片,但并不需要將存儲服務(wù)上的賬戶密碼交給它。
在這上面這一段中:
客戶端 :云打印服務(wù)
資源擁有者:你
資源服務(wù)器,授權(quán)服務(wù)器:照片云存儲服務(wù)
3 OAuth授權(quán)許可類型
3.1 授權(quán)碼許可類型(Grant Type: Authorization Code)
資源擁有者通過在授權(quán)服務(wù)器完成登錄,獲取授權(quán)碼的形式,客戶端通過Ajax請求最終兌換令牌,該種形式使得令牌對外是不可見的,一定程度上保證了令牌的安全,通常用于Web端的OAuth2.0 開發(fā)。
具體流程步驟為:
(1)資源擁有者在授權(quán)服務(wù)器完成登錄,并完成授權(quán),資源服務(wù)器重定向至客戶端,并附帶一個臨時授權(quán)碼,該授權(quán)碼是短時效性的;
(2)客戶端獲取到臨時授權(quán)碼后,通過臨時授權(quán)碼以及其他應(yīng)用信息,向資源服務(wù)器接口請求,以此來換取令牌(后端接口請求)。
3.2 隱式許可類型(Grant Type:Implicit)
有些 Web 應(yīng)用是純前端應(yīng)用,沒有后端。此時就沒有使用授權(quán)碼形式的必要了,而是直接返回令牌,省略了授權(quán)碼再去兌換令牌的步驟(該步驟本是在后端進行,目的是對前端隱藏令牌內(nèi)容)。隱式許可流程不可用于獲取刷新令牌。因為瀏覽器內(nèi)的應(yīng)用具有短暫運行的特點,只會在被加載到瀏覽器的期間保持會話。
//?請求,response_type?參數(shù)的值為token,其為一個授權(quán)頁面,用戶需要在上面完成授權(quán),授權(quán)完成后,會重定向至redirect_uri
HTTP/1.1?302?Moved?Temporarily
Location:?http://localhost:9001/authorize?response_type=token&scope=foo&client_
id=oauth-client-1&redirect_uri=http%3A%2F%2Flocalhost%3A9000%2Fcallback&state
=Lwt50DDQKUB8U7jtfLQCVGDL9cnmwHH1
Vary:?Accept
Content-Type:?text/html;?charset=utf-8
Content-Length:?444
Date:?Fri,?31?Jul?2015?20:50:19?GMT
?
//?返回,直接返回accss_token,注意此處為?#access_token
GET?/callback#access_token=987tghjkiu6trfghjuytrghj&token_type=Bearer
HTTP/1.1
Host:?localhost:9000
User-Agent:?Mozilla/5.0?(Macintosh;?Intel?Mac?OS?X?10.10;?rv:39.0)
Gecko/20100101?Firefox/39.0
Accept:?text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer:?http://localhost:9001/authorize?response_type=code&scope=foo&client_id=
oauth-client-1&redirect_uri=http%3A%2F%2Flocalhost%3A9000%2Fcallback&state=
Lwt50DDQKUB8U7jtfLQCVGDL9cnmwHH1
3.3 客戶端憑證許可類型(Grant Type:Client Credential)
后端系統(tǒng)之間需要直接通信,且本身并不代表某個特定用戶,沒有用戶對客戶端授權(quán)??蛻舳酥苯酉蚴跈?quán)服務(wù)器進行身份認(rèn)證,而授權(quán)服務(wù)器給客戶端頒發(fā)訪問令牌。需要提供客戶端id以及key(在對接前,手動申請)
其大致的請求如下:
POST?/token
Host:?localhost:9001
Accept:?application/json
Content-type:?application/x-www-form-encoded
grant_type=client_credentials&scope=foo%20bar&client_id=abcdsafdf&client_secret=qdfjadfj
3.4 斷言許可類型
在斷言許可類型下,客戶端會得到一條結(jié)構(gòu)化的且被加密保護的信息,叫作斷言,使用斷言向授權(quán)服務(wù)器換取令牌。這種許可類型只使用后端信道,與客戶端憑據(jù)許可類型很相似,沒有明確的資源擁有者參與。與客戶端憑據(jù)流程不同的是,由此頒發(fā)的令牌所關(guān)聯(lián)的權(quán)限取決于所出示的斷言,而不僅僅取決于客戶端本身。由于斷言一般來自于客戶端之外的第三方,因此客戶端可以不知道斷言本身的含義。
目前標(biāo)準(zhǔn)的斷言格式:
安全斷言標(biāo)記語言:SAML
JSON WEB TOKEN:JWT
POST?/token?HTTP/1.1
Host:?as.example.com
Content-Type:?application/x-www-form-urlencoded
Authorization:?Basic?b2F1dGgtY2xpZW50LTE6b2F1dGgtY2xpZW50LXNlY3JldC0x
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer
&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InJzYS0xIn0.eyJpc3MiOi
JodHRwOi8vdHJ1c3QuZXhhbXBsZS5uZXQvIiwic3ViIjoib2F1dGgtY2xpZW50LTEiLCJzY29wZSI....
3.5 資源擁有者許可憑證(不推薦使用)
如果資源擁有者在授權(quán)服務(wù)器上有純文本的用戶名和密碼,那么客戶端可以向用戶索取用戶的憑據(jù),然后用這個憑據(jù)換取令牌,也叫作密碼流程。
資源擁有者與之直接交互的是客戶端,而不是授權(quán)服務(wù)器。這種許可類型只使用令牌端點,并且只通過后端信道通信。
3.6 授權(quán)許可類型如何選擇

4 OAuth 安全相關(guān)
4.1 CSRF攻擊
授權(quán)碼許可和隱式許可類型中都可以使用的state 參數(shù),這個參數(shù)是一個隨機數(shù),作為接口請求參數(shù)。客戶端使用state參數(shù)來維持請求與回調(diào)之間狀態(tài)的不透明值。授權(quán)服務(wù)器在將用戶代理重定向回客戶端時包含該值。應(yīng)該使用這個參數(shù),它可以防止CSRF(cross-site request forgery,跨站請求偽造)。后續(xù)有實際例子。
4.2 授權(quán)服務(wù)器安全
授權(quán)碼使用一次之后將其銷毀。
授權(quán)服務(wù)器應(yīng)該采用精確匹配的重定向URI 校驗算法,這是唯一安全的方法。
完全按照OAuth 核心規(guī)范來實現(xiàn)授權(quán)服務(wù)器可能會導(dǎo)致它成為一個開放重定向器。如果這個重定向器能受到妥善的監(jiān)控,則情況還好,但稍有不慎則會面臨風(fēng)險。
留意在進行錯誤提示的過程中,信息有可能通過URI 片段或者Referrer 頭部遭泄露。
4.3 授權(quán)碼安全
授權(quán)碼可以避免將令牌直接暴露給其他人,但是授權(quán)碼仍可能白劫持。授權(quán)碼本身是沒有用的,特別是客戶端擁有用于自身身份認(rèn)證的密鑰的情況下。然而,原生應(yīng)用在客戶端密鑰方面存在特殊問題(APP可能需要把密鑰寫死在源代碼中導(dǎo)致泄露);
解決辦法:PKCE(Proof Key for Code Exchange)
(1)客戶端創(chuàng)建并記錄名為code_verifier的秘密信息
(2)客戶端根據(jù)code_verifier計算code_challenge(例如:密碼散列MAC)
(3)客戶端請求授權(quán)服務(wù)器,并附帶code_challenge以及code_challenge_method(計算方法,可選);
(4)授權(quán)服務(wù)器正常響應(yīng),并記錄code_challenge和code_challenge_method(與授權(quán)碼關(guān)聯(lián));
(5)客戶端接收到授權(quán)碼后,攜帶之前生成的code_verifier,執(zhí)行令牌申請請求;
(6)授權(quán)服務(wù)器計算code_challenge,檢測是否一致。
5 OAuth 令牌
OAuth 系統(tǒng)中的客戶端無須了解令牌本身的任何信息??蛻舳诵枰赖木褪侨绾螐氖跈?quán)服務(wù)器獲取令牌以及如何在資源服務(wù)器上使用令牌。但是,授權(quán)服務(wù)器和資源服務(wù)器需要了解令牌的內(nèi)容。授權(quán)服務(wù)器要知道如何生成令牌來頒發(fā)給客戶端,資源服務(wù)器要知道如何識別并驗證客戶端發(fā)送過來的令牌。
OAuth 令牌可以具有有效期,可以支持撤回,也可以永久有效,或者根據(jù)情況將這些特性組合;
令牌可以代表特定的用戶或者系統(tǒng)中所有的用戶,也可以不代表任何用戶;
令牌可以具有內(nèi)部結(jié)構(gòu),可以是隨機的無意義字符串,也可以被加密保護,甚至可以將這幾項結(jié)合起來。
授權(quán)服務(wù)器生成令牌之后,會將令牌值存儲在磁盤上的共享數(shù)據(jù)庫中(非必須)。當(dāng)受保護資源從客戶端收到令牌之后,它會在同一個數(shù)據(jù)庫中查找令牌值,以確定令牌有效。這種令牌不攜帶任何信息,只是充當(dāng)數(shù)據(jù)庫查詢的檢索值。
5.1 結(jié)構(gòu)化令牌:JWT
可參考內(nèi)容:JSON Web Tokens - jwt.io
優(yōu)勢:不向共享數(shù)據(jù)庫查詢,將所有必要的信息放在令牌內(nèi)部,授權(quán)服務(wù)器可以通過令牌本身間接地與受保護資源溝通,而不需要調(diào)用任何網(wǎng)絡(luò)API。
劣勢:頒發(fā)的令牌無法撤回。
5.1.1 JWT結(jié)構(gòu)
JWT 的核心是將一個JSON 對象封裝為一種用于網(wǎng)絡(luò)傳輸?shù)母袷?。整體機構(gòu)通過句點分割,每個部分是由Base64URL編碼的JSON對象,通過三個部分組成:
頭部(head):聲明簽名算法,以及負(fù)載類型
負(fù)載(payload):用戶數(shù)據(jù)
簽名(signature):對前兩部分的簽名
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
5.1.2 payload常用申明

5.1.3 JWT簽名:JOSE
這里分享兩種算法:
(1)HAMC算法:使用對稱密鑰,授權(quán)服務(wù)器和資源服務(wù)器都能夠生成令牌,因為它們都擁有創(chuàng)建令牌所需的密鑰。
(2)RSA算法:使用公鑰加密的話,授權(quán)服務(wù)器擁有公鑰和私鑰,可用于生成令牌,而受保護資源則只能訪問授權(quán)服務(wù)器的公鑰,用于驗證令牌。與HMAC相比,資源服務(wù)器就無法自己生成有效的令牌。
令牌請求資源服務(wù)器時,再對其進行驗簽,驗簽成功再解析payload部分。只有簽名有效才能繼續(xù)解析JWT 并檢查其內(nèi)容的一致性。如果所有檢查都通過,就可以將它交給應(yīng)用使用。
5.2 在線獲取令牌信息:令牌內(nèi)省
將令牌信息打包放入令牌本身也有其不足之處。為了包含所有必要的聲明以及保護這些聲明所需的密碼結(jié)構(gòu),令牌尺寸會變得非常大。而且,如果受保護資源完全依賴令牌本身所包含的信息,則一旦將有效的令牌生成并發(fā)布,想要撤回會非常困難。
令牌內(nèi)省:授權(quán)服務(wù)器向客戶端頒發(fā)令牌,客戶端向受保護資源出示令牌,受保護資源則向授權(quán)服務(wù)器查詢令牌狀態(tài)(內(nèi)省請求:資源服務(wù)器發(fā)送給授權(quán)服務(wù)器內(nèi)省端點的表單形式的HTTP 請求,詢問該令牌是否有效)
受保護資源在請求過程中需要向授權(quán)服務(wù)器進行身份認(rèn)證(提供client_id以及client_secret),以便授權(quán)服務(wù)器知道是誰在詢問,并可能根據(jù)詢問者的身份返回不同的響應(yīng)。內(nèi)省協(xié)議只是要求受保護資源進行身份認(rèn)證,并未規(guī)定如何認(rèn)證。
POST?/introspect?HTTP/1.1
Host:?localhost:9001
Accept:?application/json
Content-type:?application/x-www-form-encoded
Authorization:?Basic?cHJvdGVjdGVkLXJlc291cmNlLTE6cHJvdGVjdGVkLXJlc291cmNlLXNlY3JldC0x
?
token=987tghjkiu6trfghjuytrghj
?
//?內(nèi)省請求的響應(yīng)是一個JSON 對象,用于描述令牌信息。它的內(nèi)容與JWT 的載荷相似
HTTP?200?OK
Content-type:?application/json
{
????"active":?true,
????"scope":?"foo?bar?baz",
????"client_id":?"oauth-client-1",
????"username":?"alice",
????"iss":?"http://localhost:9001/",
????"sub":?"alice",
????"aud":?"http://localhost:/9002/",
????"iat":?1440538696,
????"exp":?1440538996,
}
內(nèi)省協(xié)議規(guī)范還在JWT 的基礎(chǔ)上增加了幾個聲明定義,其中最重要的是active 聲明。此聲明告訴受保護資源當(dāng)前令牌在授權(quán)服務(wù)器上是否有效,且是唯一必須返回的聲明。
使用令牌內(nèi)省會導(dǎo)致OAuth 系統(tǒng)內(nèi)的網(wǎng)絡(luò)流量增加。為了解決這個問題,允許受保護資源緩存給定令牌的內(nèi)省請求結(jié)果。建議設(shè)置短于令牌生命周期的緩存有效期,以便降低令牌被撤回 但緩存還有效的可能性。
5.3 令牌生命周期管理
OAuth 令牌通常遵循一個可預(yù)測的生命周期。令牌由授權(quán)服務(wù)器創(chuàng)建,由客戶端使用,并由受保護資源驗證。它們可能會自行失效,也可能被資源擁有者(或者管理員)從授權(quán)服務(wù)器上撤回。對于JWT等格式的令牌無效,只能過期但無法失效。
5.3.1 令牌撤回協(xié)議
OAuth 令牌撤回是一個簡單的協(xié)議,它讓客戶端可以很簡潔地告訴授權(quán)服務(wù)器將本來有效的令牌撤回??蛻舳诵枰蛞粋€專門的撤回端點發(fā)送附帶身份認(rèn)證的HTTP POST 請求,并將要撤回的令牌作為表單參數(shù)放入請求主體。
POST?/revoke?HTTP/1.1
Host:?localhost:9001
Accept:?application/json
Content-type:?application/x-www-form-encoded
Authorization:?Basic?b2F1dGgtY2xpZW50LTE6b2F1dGgtY2xpZW50LXNlY3JldC0x
token=987tghjkiu6trfghjuytrghj
客戶端身份認(rèn)證時使用的憑據(jù)與在令牌端點上使用的憑據(jù)相同(判斷是否時該客戶端申請的令牌)。授權(quán)服務(wù)器會查詢令牌值,如果找到令牌,會將它從存儲令牌的地方刪除,并返回響應(yīng)告知客戶端刪除成功。如果授權(quán)服務(wù)器未找到令牌,或者不允許出示令牌的客戶端撤回該令牌,授權(quán)服務(wù)器還是會返回操作成功,目的是不向客戶端透露本不屬于它的令牌信息。
5.3.2 刷新令牌
刷新令牌由授權(quán)服務(wù)器頒發(fā)給客戶端。在OAuth 中,訪問令牌隨時可能失效。令牌有可能被用戶撤銷,也可能過期,或者其他系統(tǒng)導(dǎo)致令牌失效。訪問令牌失效后,客戶端在使用時會收到錯誤響應(yīng)。當(dāng)然,客戶端可以再次向資源擁有者請求權(quán)限,也可以使用刷新令牌向授權(quán)服務(wù)器請求新的訪問令牌。刷新令牌還可以讓客戶端縮小它的權(quán)限范圍。如果客戶端被授予A、B、C 三個權(quán)限范圍,但是它知道某特定請求只需要A 權(quán)限范圍,則它可以使用刷新令牌重新獲取一個僅包含A 權(quán)限范圍的訪問令牌
6 可參考的線上OAuth接口文檔
QQ互聯(lián):使用Authorization_Code獲取Access_Token — QQ互聯(lián)WIKI
WeChat OAuth:準(zhǔn)備工作|微信開放文檔
支付寶 OAuth:用戶授權(quán)
Google OAuth:Using OAuth 2.0 for Web Server Applications | Google Identity Platform
Github OAuth:AuthorizingOAuth Apps - GitHub Docs
7 OAuth 線上個人OAuth申請
目前可知的,支付寶以及Github均支持以給個人身份申請接入,本次示例以Github為例。
支付寶申請地址:申請網(wǎng)頁應(yīng)用
Github申請地址:申請OAuth應(yīng)用
填寫完上述內(nèi)容后,提交會獲取到app_id以及app_secret,這樣我們就可以開始對接了,具體內(nèi)容可以參考第6部分的文檔進行
8 Postman OAuth配置
因為第7部分我們已經(jīng)申請到了github的OAuth2應(yīng)用,則我們可以直接通過Postman進行快捷的接口測試,以github獲取用戶基本信息接口為例。
該接口請求為:GET https://api.github.com/user
點開Get New Access Token進行配置,相關(guān)配置可以參考第六部分提供的文檔
AuthUrl:https://github.com/login/oauth/authorize
AccessTokenUrl:https://github.com/login/oauth/access_token

這樣我們就可以獲取到一個訪問令牌調(diào)用接口了。
粉絲福利:實戰(zhàn)springboot+CAS單點登錄系統(tǒng)視頻教程免費領(lǐng)取
???
?長按上方微信二維碼?2 秒 即可獲取資料
感謝點贊支持下哈?
