第三方登陸的實質,就是在OAuth2.0協議的基礎上,利用外部的標識來獲取賬號的內部標識而後完成登陸的過程。
具體的講,就是將三方的賬號綁定到產品自身的賬號上,當查詢到用戶第三方的賬號已經綁定了平臺的某個user_id時,直接登陸對應的賬號。例如利用微信QQ快捷登錄,能夠不用註冊APP帳號,先點擊跳轉到微信,再點擊受權進去APP中。git
1)外部標識
用來使用用戶身份的標誌,能夠是用戶名,手機號,郵箱等,每個外部標識必定和一個內部標識相關聯用以肯定一個用戶。
外部標識的做用有兩個github
2)內部標識
即產品中用於標識用戶惟一性的標誌,例如user_id,必須有,不可更改且惟一,用戶通常接觸不到內部標識。
當一個內部標識創建後,用戶全部的數據資產都會綁定到這個內部標識上。web
3)user_id
一個經常使用的內部標識,相似你的18位身份證IDspring
4)app_id
用於區別不一樣APP的ID,具備惟一性。後端
5)open_id
第三方平臺爲了用戶信息的安全,通常不會直接將用戶的內部標識給到其餘產品,而是選擇了給一個外部標識,這個open_id就是微信給各個APP用以區分微信用戶身份的外部標識。api
6)union_id
不一樣的產品的可使用同一個union_id來確認用戶的身份。瀏覽器
7)access_token
能夠理解爲通行證,有了這個通行證,就能獲取到第三方平臺指定用戶的有限信息。安全
8)OAuth 2.0
OAuth2.0就是客戶端和認證服務器之間因爲相互不信任而產生的一個受權協議,只要受權方和被受權方遵照這個協議去寫代碼提供服務,那雙方就是實現了OAuth2.0模式。服務器
(1) Client請求RO的受權,請求中通常包含:要訪問的資源路徑,操做類型,Client的身份等信息。
(2) RO批准受權,並將「受權證據」發送給Client。至於RO如何批准,這個是協議以外的事情。典型的作法是,AS提供受權審批界面,讓RO顯式批准。這個能夠參考下一節實例化分析中的描述。
(3) Client向AS請求「訪問令牌(Access Token)」。此時,Client需向AS提供RO的「受權證據」,以及Client本身身份的憑證。
(4) AS驗證經過後,向Client返回「訪問令牌」。訪問令牌也有多種類型,若爲bearer類型,那麼誰持有訪問令牌,誰就能訪問資源。
(5) Client攜帶「訪問令牌」訪問RS上的資源。在令牌的有效期內,Client能夠屢次攜帶令牌去訪問資源。
(6) RS驗證令牌的有效性,好比是否僞造、是否越權、是否過時,驗證經過後,才能提供服務。微信
核心思想:
oauth 的核心思想就是要讓第三方在不知道用戶名密碼的狀況下完成鑑權,可是沒有密碼用戶名組合根本不可能有效鑑權, oauth 實際的過程是一個李代桃疆的手法。在第一方用你的原始用戶名和密碼組合,生成另一對名稱密碼組合,這個階段叫作獲取 code 和 state,這對組合送到第二方也就是你的資源所在地,一樣較驗一遍,若是合格,給你生成一個帶有時效性的 access token, 第三方在有效期內拿着這個 access token 跳過第一方直接請求第二方的資源,至於爲何不直接返回 access token?
是由於若是使用 code 方式的話,服務器得到用戶受權後經過 302 跳轉到你的 callback URI 上,並在 url query 上帶上用於交換 accesd token 的 code ,你在瀏覽器地址欄就能夠看到這個code ,已經暴露有可能被不法應用,因此在 url 上直接返回 access token 是不安全的,而client拿到code之後換取access token是client後臺對認證服務器的訪問,而且須要clientID和client secret,不依賴瀏覽器,access token不會暴露出去。
由於單從OAuth2.0的受權過程來看,若是直接返回access_token,協議將變得更加簡潔,並且少一次Client與AS之間的交互,性能也更優,其實否則。引入authorization_code有不少妙處,主要緣由以下:
瀏覽器的redirect_uri是一個不安全信道,此方式不適合於傳遞敏感數據(如access_token),會顯著擴大access_token被泄露的風險。
但authorization_code能夠經過redirect_uri方式來傳遞,是由於authorization_code並不像access_token同樣敏感。
即便authorization_code被泄露,攻擊者也沒法直接拿到access_token,由於拿authorization_code去交換access_token是須要驗證Client的真實身份。
因爲協議須要驗證Client的身份,若是不引入authorization_code,這個Client的身份認證只能經過第1步的redirect_uri來傳遞。一樣因爲redirect_uri是一個不安全信道,這就額外要求Client必須使用數字簽名技術來進行身份認證,而不能用簡單的密碼或口令認證方式。
引入authorization_code以後,AS能夠直接對Client進行身份認證(見步驟4和5),並且能夠支持任意的Client認證方式(好比,簡單地直接將Client端密鑰發送給AS)。
OAuth 協議設計不一樣於簡單的網絡安全協議的設計,由於OAuth須要考慮各類Web攻擊,好比CSRF (Cross-Site Request Forgery), XSS (Cross Site Script), Clickjacking。
在redirect_uri中引入state參數就是從瀏覽器安全角度考慮的,有了它就能夠抵制CSRF攻擊。
開發以前,須要前往第三方登陸的開發者平臺QQ、新浪微博、Github,註冊帳號並填寫信息申請接入,成功後會給你一個ID和祕鑰,之後你就經過該ID和祕鑰來獲取令牌,從而實現第三方登陸。申請ID和祕鑰時Github不須要審覈,因此本文主要介紹GitHub實踐。QQ、微信、微博等須要審覈,但流程和原理都是同樣的。
登錄我的GitHub帳號,進入【Settings】->選擇【applications】->選擇【Developer applications】-> 【Register a new OAuth application】
註冊以後會獲得 github提供的client id和client secret
以Github爲例,其相應的API地址分別爲:
https://github.com/login/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&state={state}
http://localhost:8888/oauth/github/callback?code={code}&state={state}
https://github.com/login/oauth/access_token
https://api.github.com/user?access_token={access_token}
若是要寫
如今,咱們須要作下列事情:
引入必要的依賴,就能夠開發了,前期代碼寫的有些繁瑣,後來發現巧妙使用配置文件application.yml中會更加簡潔,由於Spring已經整合好了整個Oauth2.0流程,能夠減小了不少代碼。
邏輯代碼就不具體展現了,重中之重的配置文件application.yml內容以下
github-base-url: https://github.com/login spring: security: oauth2: client: registration: github: client-id: 4255eebca50558bd0579(Your client-id) client-secret: XXXXX(Your client-secret) authorizationGrantType: authorization_code redirect_uri_template: "{baseUrl}/login/oauth2/code/{registrationId}" clientName: github-client provider: github: token-uri: ${github-base-url}/oauth/access_token authorization-uri: ${github-base-url}/oauth/authorize user-info-uri: https://api.github.com/user server: port: 8888
1.用戶點擊github登陸本地應用引導用戶跳轉到第三方受權頁
跳轉地址:https://github.com/login/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&state={state}
client_id,client_secret是註冊好Oauth APP後github提供的,須要寫在本地代碼或者配置文件中,state也是在本地生成的。redirect_uri 就是在GitHub官網填的Authorization callback URL。
此時帶着state等參數去申請受權,但此時還沒有登錄,未能經過authorize,GitHub返回code參數。
2.受權成功後會重定向帶參數訪問上面的redirect_uri,並多了一個code參數
後臺接收code這個參數,咱們帶着這個code再次訪問github 地址
https://github.com/login/oauth/access_token?client_id=xxx&client_secret=xxx&code=xxx&redirect_uri=http://127.0.0.1:8080/cqput-bbs/User/RegisteredByGithub.do
3.經過state參數和code參數,成功獲取access_token
有了access_token,只須要把access_token參數放在URL後面便可,就能夠換取用戶信息了。
訪問地址:https://api.github.com/user?access_token=xxx;
4.獲得github受權用戶的我的信息,就代表受權成功
整個流程相似於下圖,放在這裏方便你們理解。
本文主要是結合本身所學知識,和衆多參考資料,探討了本身對OAuth2.0原理和第三方登陸實質的一些理解,完成了第三方登陸之GitHub的實踐。 但願能對你們有所幫助~ 有問題歡迎留言交流,不足之處還請多多指正。