🎉🎉歡迎來到我的CSDN主頁!🎉🎉
🏅我是Java方文山,一個在CSDN分享筆記的博主。📚📚
🌟推薦給大家我的專欄《OAuth 2》。🎯🎯
👉點擊這里,就可以查看我的主頁啦!👇👇
Java方文山的個人主頁
🎁如果感覺還不錯的話請給我點贊吧!🎁🎁
💖期待你的加入,一起學習,一起進步!💖💖
一、OAuth2的簡介
1.什么OAuth2
OAuth 2?是一種授權框架,允許第三方應用通過用戶授權的形式訪問服務中的用戶信息,最常見的場景是授權登錄;再復雜一點的比如第三方應用通過 Github 給開發者提供的接口訪問權限內的用戶信息或倉庫信息。OAuth2 廣泛應用于 web 、桌面應用、移動 APP 的第三方服務提供了授權驗證機制,以此實現不同應用間的數據訪問權限。 下面分別從不同角色、授權類型、使用場景及流程的緯度詳細介紹 OAuth2
2.OAuth Roles
OAuth 定義了四種角色
- 資源擁有者 (Resource Owner)
- 客戶端 (Client)
- 資源服務器 (Resource Server)
- 授權服務器 (Authorization Server)
資源擁有者其實就是真實的用戶,用戶授權給第三方應用訪問在其他系統的用戶信息。第三方應用訪問授權用戶的信息范圍?scope
?屬于申請接入服務時選擇的權限之內(例如:讀或寫訪問權限)
資源服務控制用戶的信息,授權服務驗證用戶提供的信息是否正確并返回 access token 給第三方應用。 站在第三方開發者的角度看,被接入的系統提供的服務 API 同時實現了資源和授權角色。在這里把資源服務端和授權服務端統一為“服務角色或 API 角色”。
客戶端就是要求接入的第三方應用,獲取用戶在提供服務的系統的賬戶信息。對于客戶端而言,最終獲取到用戶在服務端的賬戶信息首先需要用戶授權,用戶授權后傳給提供服務端驗證成功之后返回 access token ,在通過 access token 請求提供服務的系統(在這里我們成為 API ,下文也是)獲取用戶在 API 中的賬戶信息。
3.授權流程
接下來文中提到的客戶端均為第三方應用,服務端均為被接入的服務。譬如拉勾網有微博登錄功能,那么拉勾網就是客戶端,微博就是服務端。
剛剛解釋了 OAuth 系統中角色的概念,接下來可以解釋整個授權的流程。
流程圖解釋:
- 用戶點擊客戶端提供的授權請求
- 客戶端請求服務的授權頁面呈現給用戶,用戶點擊確認授權后服務端返回授權許可憑證給客戶端
- 客戶端通過步驟二接收到的授權許可憑證及在服務端注冊的應用信息請求服務端
- 如果步驟三驗證通過服務端則返回 access token 給客戶端
- 客戶端通過第四步獲取的 access token 請求服務端獲取資源
- 如果服務端校驗 access token 成功,則返回指定資源給客戶端
以上步驟是 OAuth2 授權登錄的步驟,當然不同類型的授權許步驟會不一樣,下文會詳細逐一討論。
二、第三方應用創建
第三方接入某平臺的 OAuth 2 服務之前,通常需要在平臺提供的注冊網站(通常叫做 developer" or "API")新建一個應用,注冊成功之后平臺會生成應用的 ID 和密碼。 讀者可以訪問 Github 的開發中心看看,國內寫的規范的有?coding developer
在平臺的注冊頁面至少得提供如下信息
- 應用名稱
- 應用網址
- 回調鏈接
回調域名的作用:用戶點擊同意按鈕之后,服務端向客戶端返回授權碼或 access token ,當然如果是禁止操作也需回調告知客戶端結果。
在 OAuth 2 服務提供平臺新建一個應用之后,平臺會提供一對客戶端 ID 和密碼作為客戶端憑證。客戶端 ID 是可以公開的字符串,用以構建授權請求鏈接;用戶授權之后,客戶端使用服務端的授權碼和平臺分配的密碼獲取 access token 。密碼應當妥善保管以免泄漏。
1.授權許可
在第一張授權流程圖中,前四步包含了獲取授權許可獲取 access token ,授權許可有四種類型,服務端返回哪種類型取決于客戶端在請求鏈接中構建的?response_type
?參數。四種類型的授權許可有不同的應用場景:
- 授權碼:通過授權碼,服務端通過 Ajax 把 access token 返回給客戶端
- 隱式:用于移動 APP 或 web 應用(應用運行在用戶的設備上)
- 用戶密碼憑證:同一個公司不同系統之間內部賬戶互聯互通,比如國內某社區的代碼托管系統通過社區的賬戶也可以登錄。
- 客戶端憑證:第三方應用自身服務訪問提供 OAuth2 服務提供的平臺資源
1.1.授權碼 (Grant Type: Authorization Code)
授權碼是 OAuth2 授權最廣泛的方式,得益于平臺給第三方應用分配的 ID 和密碼都是隱藏在第三方應用的后端代碼中。因為授權碼是基于重定向的方式,要想使用授權碼的方式,第三方應用必須能夠調用用戶系統中的應用(譬如瀏覽器)、和提供一個接口接收平臺服務的回調獲取授權碼。
一步步解釋授權碼的流程圖
步驟一:構建獲取授權碼請求鏈接
下文提到的例子都是基于 digiterocean 的 OAuth2
第一步是構建一個請求 Auth Server 獲取授權碼的鏈接,向服務端發起請求
https://cloud.digitalocean.com/v1/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read
分解請求鏈接:
- https://cloud.digitalocean.com/v1/oauth/authorize?表示服務端授權 endpoint
- client_id?平臺分配給第三方應用的 ID
- redirect_uri=CALLBACK_URL?第三方開發者在平臺新建第三方應用時填寫的回調 URL
- response_type=code?指定服務端返回授權碼
- scope=read?指定第三方應用請求權限類型
步驟二:用戶授權給第三方應用
當用戶點擊第一步構建的鏈接之后,在用戶已經登錄服務端之后才能點擊確認授權(譬如想通過微信登錄某個第三方網址,你必須首先已經登錄微博)。這是平臺會給用戶提供一個頁面給用戶確認是否授權。
步驟三:服務端給客戶端返回授權碼
當用戶點擊同意授權之后,服務端發起一個請求重定向到第三方平臺填寫的回調鏈接,且請求鏈接中同時包含了服務端生成的授權碼。
https://dropletbook.com/callback?code=AUTHORIZATION_CODE
步驟四:第三方應用請求服務端,獲取 access token
客戶端獲取到服務端返回的授權碼之后,接著使用授權碼和平臺分配的密碼請求服務端獲取服務端的 access token 。第三方應用后端代碼拼接的 URL 格式形似:
https://cloud.digitalocean.com/v1/oauth/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=CALLBACK_URL
在這里需注意兩個參數,其一是?client_secret
?沒有暴露出去,在第三方應用后端代碼中拼接請求鏈接;另一是 redirect_uri ,這里不是在平臺新建應用時填寫的回調鏈接,而是第三方應用已經實現的另一個 action 處理服務端返回 access token 的請求。
步驟五:第三方應用接收 access token
如果第四部客戶端發送的信息被服務端校驗成功,服務端則返回 access token ,有一些平臺同時也同時傳遞 refresh token 。返回的 json 信息形似:
{
"access_token":"ACCESS_TOKEN",
"token_type":"bearer",
"expires_in":2592000,
"refresh_token":"REFRESH_TOKEN",
"scope":"read",
"uid":100101,
"info":{"name":"Mark E. Mark","email":"mark@thefunkybunch.com"}
}
至此,已經走完 oauth 2 授權碼的方式所有流程。在 access_token 沒有失效的前提下,可通過 access_token 可以訪問平臺服務端提供的資源。另外如果還提供了 refresh_token ,在 access_token 失效的情況下,可以通過 refresh_token 再次去獲取有效的 access_token 。
1.2.隱式 (Grant Type: Implicit)
相比授權碼的授權許可這種后端實現,隱式授權類型在應用于前端實現(移動客戶端或者瀏覽器),其缺陷就是并不保證平臺分配給第三方平臺的密碼憑證足夠安全。隱式授權同樣也是基于重定向的方式,但是?access_token 通過網頁重定向返回給第三方平臺而不是通過接口調用的方式?暴露了 access_token 在重定向鏈接中,這點和授權碼不同。另外,也不支持服務端校驗客戶端第三方應用密碼,只是依賴在平臺新建應用是填寫的回調鏈接。
隱式授權不支持 refresh_token
授權大概流程如下:用戶請求授權,同意授權后服務端把 access_token 拼接到回調鏈接上通過瀏覽器重定向到客戶端,然后客戶端獲取到 access_token 。
通過流程圖可看出在第三步和授權碼不同的是服務端重定向到網頁而不是通過接口把 access_token 返回給客戶端。
步驟一:構建隱式授權請求鏈接
與授權碼的步驟一差不多一致,只是?response_type
?字段的參數值為?token
步驟二:用戶授權給第三方
與授權碼授權的步驟二完全一致
步驟三:通過服務端重定向鏈接,User-agent (瀏覽器或者 APP) 獲取 access_token
與授權碼不同的是,用戶點擊授權之后服務端通過把 access_token 通過網頁重定向到回調鏈接,客戶端通過重定向鏈接才能獲取到access_token ;而授權碼獲取 access_token是通過服務端通過 ajax 請求的形式直接訪問第三方應用的后端接口,把 access_token傳給第三方后端。
步驟三:前端根據重定向調整
前端瀏覽器重定向請求第三方平臺的后端
步驟五:第三方應用后端通過腳本獲取在重定向鏈接中的 access_token
第三方應用后端通過腳本獲取在重定向鏈接上的 access_token
步驟六:User-Agent 執行第三方應用后端返回的腳本把 access_token 返回給第三方平臺后端。
1.3用戶密碼憑證
用戶直接給第三方應用提供在提供服務端賬號密碼,獲取服務端的 access_token。這種授權方式常用于一個企業不同服務之間的賬號互聯互通。 用戶給第三方應用提供賬號密碼之后,客戶端發送 POST 請求給服務端獲取access_token
https://oauth.example.com/token?grant_type=password&username=USERNAME&password=PASSWORD&client_id=CLIENT_ID
如果服務端校驗客戶端(第三方應用)傳過來的賬戶密碼正確,則把 access_token返回給客戶端,用戶授權完成。
1.4.客戶端憑證
這種授權方式常用于第三方應用想要更改自身在服務提供方注冊的應用信息,比如更改應用描述或回調鏈接地址。
第三方應用通過發送服務端分配的 ID 和密碼給后端校驗,POST 的 URL 格式形似:
https://oauth.example.com/token?grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET
Access Token 和 Refresh Token
第三方應用從服務提供平臺獲取到有效的 access_token 之后,即可根據平臺提供的接口訪問服務端的資源。
curl -X POST -H "Authorization: Bearer ACCESS_TOKEN""https://api.digitalocean.com/v2/$OBJECT"
如果服務提供平臺支持 refresh_token ,那么第三方應用的 access_token 失效之后,可通過 refresh_token 再次獲取有效的 access_token
例如 digitalocean 支持第三方應用通過 POST 請求再此獲取有效的 access_token
https://cloud.digitalocean.com/v1/oauth/token?grant_type=refresh_token&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&refresh_token=REFRESH_TOKEN
?
到這里我的分享就結束了,歡迎到評論區探討交流!!
💖如果覺得有用的話還請點個贊吧 💖