Spring Security OAuth2


Spring Security OAuth2

標簽(空格分隔): Spring


1. oAuth(Open Authorization)

OAuth協議為用戶資源的授權(增刪改查)提供了一個安全, 開放而又簡易的標准. 和以往授權方式不同之處是oAuth的授權不會使第三方觸及到用戶的賬號信息. 即第三方無需使用用戶的用戶名和密碼就可以申請獲得該用戶的資源授權. 因此oAuth本身第安全是無害的.


2. Spring Security


Spring Security是一個安全框架, 可以為Spring的企業級應用系統提供聲明式的安全訪問控制. Spring Security基於Servlet過濾器, IOC和AOP, 為Web請求和方法調用提供身份認證和授權處理, 避免了代碼耦合, 減少了大量的重復工作.


3. 應用場景

對於一個系統來說, 他可能提供了不同的服務在不同的設備上, 此時我們需要在不同的設備上去訪問這些服務. 那么用戶如何去獲取自己的那部分資源呢? 可以想到的做法就是提供自己的賬號和密碼, 登錄成功之后就可以獲取了. 但是其存在以下問題.

  • 對於相關性不高的服務, 我們可能對其采取分別部署, 那么我們訪問不同服務的時候都需要登錄么?
  • 如果第三方程序想要接入我們的服務, 難道我們需要提供賬號和密碼給第三方應用程序, 讓他記錄后再訪問我們的資源么?
  • 如何限定 第三方 服務的訪問權限?
  • 如果有用戶修改了密碼收回了權限, 那么第三方的應用程序會全部失效.
  • 密碼知道的人越多, 泄露的可能就越大.

oAuth在"客戶端"與"服務提供商"之間, 設置了一個授權層. 客戶端無法直接登錄訪問服務提供商, 只能登錄授權層, 以此將用戶和客戶端區分開來, 客戶端登錄授權層 所有的令牌(token), 和用戶密碼不同. 用戶在登錄的時候, 指定授權層令牌的權限范圍和有效期. 客戶端登錄授權層以后, 服務商根據令牌的授權范圍和有效期, 向客戶端提供用戶的存儲資料.

其實上面說的和我們在做微服務的時候用的SSO, 差不多. 在網關把服務聚合完畢之后, 通過網關試圖去訪問服務, 但是在沒有授權令牌(token)的時候, 服務提供者會將我們的請求踢到SSO模塊. 在哪里進行授權獲取token之后, 才可以訪問SSO. 其SSO就是服務和客戶端(瀏覽器)之間的授權層.

SSO流程. 用戶訪問服務, 發現沒有token, 服務將請求重定向到SSO. 輸入賬號密碼之后, 生成token作為Cookie傳給瀏覽器. token作為鍵, 用戶信息作為值存儲到Redis緩存中. 再次訪問服務提供者, 服務提供者根據Cookie中的token, 查詢Redis, 得到用戶信息, 授權訪問. 有比較大的相似之處.

此處輸入圖片的描述


4. 開放平台

這個一般是類似於你做了一個QQ這樣的產品, 其他的服務提供商想要讓QQ的龐大用戶群去使用他們的服務的時候, 一般會使用你做的開放平台, 讓其他的服務提供商通過你的認證服務器


5. 令牌的刷新和訪問

Access Token是客戶端訪問資源服務器的令牌, 擁有這個令牌代表着得到了用戶的授權. 然而這個授權應該是臨時的, 有一定有效期的(SSO中利用Redis的過期機制實現). 這個可以降低因為token泄露帶來的風險. 引入有效期之后token過期, 用戶就需要重新登錄, 如果有效期過短, 那么用戶體驗就很差, 為了兼顧安全和用戶體驗, oAuth2引入了Refresh Token機制.

5.1 Refresh Token

Refresh Token的作用是用來刷新Access Token的, 認證服務器提供一個刷新接口, 例如:
www.x-power.press/refresh?refresh_token=&client_id=
傳入 Refresh Token和Client Id之后, 認證服務器通過驗證后會返回一個全新的Access Token. 為了安全oAuth2做了一下兩點:

  1. oAuth2要求, refresh token一定是保存在客戶端的服務器上, 而不能存放在客戶端上, 調用接口的時候, 也是服務器到服務器的訪問(資源服務器到認證服務器)
  2. oAuth2引入了client_secret機制. 即每一個client_id都對應一個client_secret. 這個client_secret會在客戶端申請client_id的時候,隨着client_secret一起分配給客戶端(分配 不是放入). 客戶端必須要client_secret妥善的保存在服務器上, 絕對不能泄露, 刷新Access Token的時候需要驗證client_secret.

實際上的刷新接口類似於:
http://www.x-power.press/refresh?refresh_token=&client_id=&client_secret= .
以上就是refresh token的運行原理, refresh token的有效期非常長, 會在用戶授權的時候, 隨着Access token一定重定向到回調URL傳遞給客戶端.

實際流程如下:

  1. 第三方應用請求授權(我們的應用)
  2. 用戶同意授權(輸入賬號密碼), 並返回一個授權碼.
  3. 第三方應用根據授權碼,向授權服務器認證授權.
  4. 授權服務器校驗授權碼, 校驗通過返回第三方應用令牌Access token
  5. 第三方應用根據令牌, 向資源服務器請求相關資源
  6. 資源服務器驗證令牌, 校驗通過, 並返回給第三方所請求的資源.

6. 授權模式

客戶端必須得到用戶的授權, 才能獲得令牌. oAuth2定義了四種授權方式.

  • implicit code: 簡化模式, 太監被二次閹割之后的版本.
  • authorization code: 授權碼模式.
  • resource owner password credentials: 密碼模式
  • client credentials :客戶端模式

6.1 簡化模式

簡化模式用於純靜態頁面應用. 所謂的純靜態頁面應用, 也就是應用沒有在服務器上執行代碼的權限, 只有JS代碼的控制權. (通過GitHub制作自己的博客, 就是純靜態應用. 但是其可以存儲數據, 所以我認為在這里下面的聲明不成立, 是可以做到Refresh token刷新的.)

該場景之下, 應用是沒有持久化存儲的能力的. 因此, 按照oAuth2的規定, 這種應用是拿不到 Refresh Token的. 其整個授權流程如下:
此處輸入圖片的描述

6.2 授權碼模式

授權碼模式適用於有自己服務器的應用, 它是一個一次性的臨時憑證, 用來換區access_tokenrefresh_token. 認證服務器提供了一個類似這樣的接口:
https://www.x-power.com/exchange?code=&client_id=&client_secret=
其需要傳入code, client_id以及client_secret. 驗證通過之后, 返回access_token, 一旦換取成功code`立即作廢. 不能再使用第二次.

此處輸入圖片的描述

這個 code 的作用是保護 token 的安全性。上一節說到,簡單模式下,token 是不安全的。這是因為在第 4 步當中直接把 token 返回給應用。而這一步容易被攔截、竊聽。引入了 code 之后,即使攻擊者能夠竊取到 code,但是由於他無法獲得應用保存在服務器的 client_secret,因此也無法通過 code 換取 token。而第 5 步,為什么不容易被攔截、竊聽呢?這是因為,首先,這是一個從服務器到服務器的訪問,黑客比較難捕捉到;其次,這個請求通常要求是 https 的實現。即使能竊聽到數據包也無法解析出內容。

有了這個 code,token 的安全性大大提高。因此,oAuth2.0 鼓勵使用這種方式進行授權,而簡單模式則是在不得已情況下才會使用

6.3 密碼模式

密碼模式中,用戶向客戶端提供自己的用戶名和密碼。客戶端使用這些信息,向 "服務商提供商" 索要授權。在這種模式中,用戶必須把自己的密碼給客戶端,但是客戶端不得儲存密碼。這通常用在用戶對客戶端高度信任的情況下,比如客戶端是操作系統的一部分。

一個典型的例子是同一個企業內部的不同產品要使用本企業的 oAuth2.0 體系。在有些情況下,產品希望能夠定制化授權頁面。由於是同個企業,不需要向用戶展示“xxx將獲取以下權限”等字樣並詢問用戶的授權意向,而只需進行用戶的身份認證即可。這個時候,由具體的產品團隊開發定制化的授權界面,接收用戶輸入賬號密碼,並直接傳遞給鑒權服務器進行授權即可。

此處輸入圖片的描述

有一點需要特別注意的是,在第 2 步中,認證服務器需要對客戶端的身份進行驗證,確保是受信任的客戶端。

6.4 客戶端模式

如果信任關系再進一步,或者調用者是一個后端的模塊,沒有用戶界面的時候,可以使用客戶端模式。鑒權服務器直接對客戶端進行身份驗證,驗證通過后,返回 token。

此處輸入圖片的描述


7. RBAC(Role-Based Access Control)

用戶通過角色身份和不同的權限相關聯. 簡單地說就是, 一個用戶有若干個角色,每一個角色有若干權限. 這樣就構成了用戶-角色-權限的授權模型. 在這種模型之中, 用戶和角色之間, 角色和權限之間. 一般就是一對多的關系.

此處輸入圖片的描述

在oAuth2中我們需要對靜態資源和動態資源的訪問都做出控制.

  • 靜態資源: 數據列(用戶表中密碼不想讓你訪問, 你只可以訪問用戶名,圖像.) 縱向資源
  • 動態資源: 文章, 相冊. 橫向資源

對於每一類資源的CRUD. 都擁有這四個中的哪幾個權限?

Python的Django 自帶的后台 就用的是oAuth2, 在自帶后台里面就可以設置對於每一類資源的訪問權限, 控制權限.



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM