做者:Barret李靖
連接:https://www.zhihu.com/question/19781476/answer/81020455
來源:知乎
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。git
本文將以用戶使用 github 登陸網站留言爲例,簡述 OAuth 2.0 的運做流程。github
假如我有一個網站,你是我網站上的訪客,看了文章想留言表示「朕已閱」,留言時發現有這個網站的賬號纔可以留言,此時給了你兩個選擇:一個是在個人網站上註冊擁有一個新帳戶,而後用註冊的用戶名來留言;一個是使用 github 賬號登陸,使用你的 github 用戶名來留言。前者你以爲過於繁瑣,因而慣性地點擊了 github 登陸按鈕,此時 OAuth 認證流程就開始了。web
須要明確的是,即便用戶剛登陸過 github,個人網站也不可能向 github 發一個什麼請求便可以拿到訪客信息,這顯然是不安全的。就算用戶容許你獲取他在 github 上的信息,github 爲了保障用戶信息安全,也不會讓你隨意獲取。因此操做以前,個人網站與 github 之間須要要有一個協商。api
## 1. 網站和 Github 之間的協商安全
Github 會對用戶的權限作分類,好比讀取倉庫信息的權限、寫入倉庫的權限、讀取用戶信息的權限、修改用戶信息的權限等等。若是我想獲取用戶的信息,Github 會要求我,先在它的平臺上註冊一個應用,在申請的時候標明須要獲取用戶信息的哪些權限,用多少就申請多少,而且在申請的時候填寫你的網站域名,Github 只容許在這個域名中獲取用戶信息。網站
此時個人網站已經和 Github 之間達成了共識,Github 也給我發了兩張門票,一張門票叫作 Client Id,另外一張門票叫作 Client Secret。spa
## 2. 用戶和 Github 之間的協商code
用戶進入個人網站,點擊 github 登陸按鈕的時候,個人網站會把上面拿到的 Client Id 交給用戶,讓他進入到 Github 的受權頁面,Github 看到了用戶手中的門票,就知道這是個人網站讓他過來的,因而它就把個人網站想要獲取的權限擺出來,並詢問用戶是否容許我獲取這些權限。blog
// 用戶登陸 github,協商 GET https://github.com/login/oauth/authorize // 協商憑證 params = { client_id: "xxxx", redirect_uri: "http://my-website.com" }
若是用戶以爲個人網站要的權限太多,或者壓根就不想我知道他這些信息,選擇了拒絕的話,整個 OAuth 2.0 的認證就結束了,認證也以失敗了結。若是用戶以爲 OK,在受權頁面點擊了確認受權後,頁面會跳轉到我預先設定的 `redirect_uri` 並附帶一個蓋了章的門票 code。token
// 協商成功後帶着蓋了章的 code Location: http://my-website.com?code=xxx
這個時候,用戶和 Github 之間的協商就已經完成,Github 也會在本身的系統中記錄此次協商,表示該用戶已經容許在個人網站訪問上直接操做和使用他的部分資源。
## 3. 告訴 Github 個人網站要來拜訪了
第二步中,咱們已經拿到了蓋過章的門票 code,但這個 code 只能代表,用戶容許個人網站從 github 上獲取該用戶的數據,若是我直接拿這個 code 去 github 訪問數據必定會被拒絕,由於任何人均可以持有 code,github 並不知道 code 持有方就是我本人。
還記得以前申請應用的時候 github 給個人兩張門票麼,Client Id 在上一步中已經用過了,接下來輪到另外一張門票 Client Secret。
// 網站和 github 之間的協商 POST https://github.com/login/oauth/access_token // 協商憑證包括 github 給用戶蓋的章和 github 發給個人門票 params = { code: "xxx", client_id: "xxx", client_secret: "xxx", redirect_uri: "http://my-website.com" }
拿着用戶蓋過章的 code 和可以標識我的身份的 client_id、client_secret 去拜訪 github,拿到最後的綠卡 access_token。
// 拿到最後的綠卡 response = { access_token: "e72e16c7e42f292c6912e7710c838347ae178b4a" scope: "user,gist" token_type: "bearer", refresh_token: "xxxx" }
// 訪問用戶數據 GET https://api.github.com/user ?access_token=e72e16c7e42f292c6912e7710c838347ae178b4a
上一步 github 已經把最後的綠卡 access_token 給我了,經過 github 提供的 API 加綠卡就可以訪問用戶的信息了,能獲取用戶的哪些權限在 response 中也給了明確的說明,scope 爲 user 和 gist,也就是隻能獲取 user 組和 gist 組兩個小組的權限,user 組中就包含了用戶的名字和郵箱等信息了。
// 告訴我用戶的名字和郵箱 response = { username: "barretlee", email: "barret.china@gmail.com" }
整個 OAuth2 流程在這裏也基本完成了,文章中的表述很粗糙,好比 access_token 這個綠卡是有過時時間的,若是過時了須要使用 refresh_token 從新簽證。重點是讓讀者理解整個流程,細節部分能夠閱讀 [RFC6749 文檔](RFC Reader - An online reader for IETF RFCs)。