html
java
目錄web
- 1. 什麼是單點登陸
- 2. 用戶登陸
- 2.1 認證方式
- 2.2 受權方式
- 2.3 第一方登陸架構實現
- 2.4 第三方登陸架構實現
- 2.5 第一方登陸和第三方登陸的受權區別
- 2.6 登陸架構實現小結
- 3. 權限控制
- 3.1 分佈式鑑權架構
- 3.2 集中式鑑權架構
- 3.3 分佈式和集中式鑑權的優缺點
- 3.4 訪問控制的粒度
- 3.4.1 Http方法級別
- 3.4.2 API接口級別
- 3.4.3 API實現級別
- 4. 小結
- 5. 參考資料
在互聯網應用開發中,應用服務的用戶登陸和權限控制是相當重要的一個環節,直接影響到應用的安全運營,也影響到用戶的隱私保護,所以用戶登陸和權限控制是互聯網應用開發的必要功能組件, 其涉及到認證、受權、鑑權和權限控制四個功能環節。本文將梳理互聯網應用開發中的單點登陸(single-sign-on)技術架構實現,單點用戶登陸也被稱爲統一用戶登陸。redis
- 注1:本文討論的互聯網應用開發,主要是指web應用和移動應用開發兩個技術領域。
- 注2:本文所討論的認證、受權、鑑權和權限控制的概念定義來自其這篇文章。所以,在閱讀本文以前,建議先請閱讀前篇文章。
1. 什麼是單點登陸
單點登陸SSO不只僅是實現用戶登陸這單一功能,它更是一個技術架構,一個解決方案,可以提供統一的認證、受權、鑑權和權限控制,提供相應的組件,方便用戶的使用,以及應用的開發快速接入。因此,單點登陸不是一個簡單的登陸模塊。spring
單點登陸,從字面來講,是讓用戶使用同一帳號能夠訪問不一樣應用服務,並且用戶只需登陸一次(輸入一次用戶名和密碼)即可實現屢次受權。單點登陸可以很大程度上方便用戶的登陸操做。這是從用戶的角度出發來看單點登陸。後端
單點登陸還須要考慮的另一個重要需求,是方便應用的對接使用,單點登陸架構必須提供相應的客戶端組件和配置,使得應用能夠簡單、方便、快速地接入單點登陸功能,同時實現安全的權限控制。跨域
所以,單點登陸做爲一個安全技術架構,其主要包括用戶登陸和權限控制兩大功能需求,前者涉及認證和受權環節,後者涉及鑑權和權限控制環節。瀏覽器
2. 用戶登陸
用戶登陸的過程通常會涉及到用戶認證和受權兩個環節,這兩個環節每每一併發生,即在確認用戶身份的同時,也完成用戶的受權。緩存
根據登陸功能模塊的提供方,能夠將登陸劃分爲第一方登陸和第三方登陸兩種類型,安全
- 第一方登陸:應用的登陸服務由本身提供。因爲是己方登陸和己方應用,因此登陸服務和應用服務之間相互可信,這大大方便了受權過程。
- 第三方登陸:應用的登陸服務由第三方提供,使用第三方的用戶帳號登陸,好比經過微信、QQ、支付寶帳號進行登陸等等。目前各大互聯網開放平臺大多采用業界標準的OAuth 2.0受權碼模式實現第三方登陸。
第一方登陸和第三方登陸,在用戶認證技術的實現上沒有太大差異,可是受權流程有區別。具體的受權流程和區別在下文的架構實現中討論。
2.1 認證方式
在互聯網開發中,常見的認證方式有,
- 用戶名和密碼
- 手機短信驗證碼
- 手機應用二維碼掃描
- 用戶手勢
- 基於時間序列和用戶相關的一次性口令
本文爲了方便討論,將使用簡單的http基本認證(http basic authentication)方式進行用戶登陸,即用戶名和密碼的方式。更多的認證方式,通常能夠經過identity provider的擴展接口來實現。
2.2 受權方式
一旦用戶登陸成功,便可獲取到相應的受權信息。
在互聯網應用開發領域,受權的實現技術主要包括以下幾種,
- 經過web服務器的session機制,一個訪問會話保持着用戶的受權信息
- 經過web瀏覽器的cookie機制,一個網站的cookie保持着用戶的受權信息
- 頒發受權令牌(token),一個合法有效的令牌中保持着用戶的受權信息
前面二者常見於web開發,須要有瀏覽器的支持。而對於移動應用及其其它沒法使用cookie的場景中,大多能夠採用token的實現並經過header方式攜帶該受權信息在請求中。
本文爲了同時支持web應用和移動應用的受權,受權信息將以受權令牌(token)形式頒發,對於web應用,該受權令牌經過cookie攜帶於請求中,而對於移動應用,則經過header方式攜帶於請求中。
2.3 第一方登陸架構實現
因爲是己方登陸實現,因此登陸服務和應用服務之間相互可信,這大大方便了受權過程。
在第一方登陸的場景下,通常能夠經過兩種方式得到受權,
- 若應用經過瀏覽器訪問,則能夠經過同域cookie方式實現共享受權
- 若應用不是瀏覽器訪問,或者沒法經過cookie技術,則能夠直接經過用戶名和密碼來換取受權。須要注意的是,應用服務能夠拿到用戶名和密碼等敏感信息,這是基於可信應用的先決條件。
代碼實現(待開發)
一個簡單的架構實現以下,
圖中亮紅色線和方格爲單點登陸架構所需實現的組件和功能,其主要包括,
- 單點登陸模塊:提供用戶登陸界面,實現跳轉返回,受權令牌(token)的頒發、校驗和註銷
- Web filter:獲取請求中的受權令牌並校驗,若合法則經過請求,不然返回錯誤消息。
對於web應用,經過共享cookie的方式獲取受權,整個流程交互以下,
- 用戶經過瀏覽器訪問web服務
- 後端服務中一個通用的web filter校驗請求,若發現請求中沒有受權令牌,則跳轉至用戶登陸模塊,讓用戶進行登陸
- 用戶輸入用戶名和密碼,若登陸成功,則將受權令牌存儲在瀏覽器的cookie中
- 將用戶跳轉回用戶的訪問頁面,此時請求中cookie將自動帶上受權令牌
- 後端服務的web filter校驗請求cookie中的受權令牌,若合法且有效,則用戶能夠正常訪問後端服務,不然返回錯誤消息,提示用戶再次登陸。
- 用戶註銷登陸時,web應用服務將存儲在瀏覽器cookie中的受權令牌清除,並註銷redis中的令牌。
對於移動應用,經過用戶名和密碼的方式獲取受權,整個流程交互以下,
- 用戶打開移動應用,應用提示用戶登陸
- 用戶輸入用戶名和密碼,若登陸成功,則將受權令牌返回給移動應用,存儲在手機上的應用存儲空間。
- 進入應用後,移動應用訪問後端服務,受權令牌攜帶在請求header中
- 後端服務中一個通用的web filter對請求header中的受權令牌進行校驗,若合法且有效,則用戶能夠正常訪問後端服務,不然提示用戶登陸。
- 用戶註銷登陸時,移動應用將受權令牌清除,並註銷redis中的令牌。
因爲移動應用沒法像web應用同樣,經過瀏覽器cookie的方式自動攜帶受權信息,移動應用須要本身處理受權信息的存儲和請求發送。
2.4 第三方登陸架構實現
相比於第一方登陸,第三方登陸最大的好處在於,可讓用戶使用一個經常使用的第三方帳號直接登陸,例如微信、QQ、淘寶帳號等,省去了用戶註冊帳號的步驟,也免去用戶記憶各類應用帳號密碼的煩惱,方便了用戶的快速使用,進而下降用戶接入成本。
對於第三方登陸,目前各大互聯網開放平臺大多采用業界標準的OAuth 2.0受權碼模式。對於OAuth 2.0的受權碼模式和更多詳細介紹將有另一篇文章討論,這裏對其不擴展。
代碼實現(待開發)
一個簡單的架構實現以下,
圖中亮紅色線和方格爲單點登陸架構所需實現的組件和功能,其包括,
- OAuth 2.0受權服務器:提供用戶登陸受權,實現跳轉返回,受權令牌(token)的頒發、校驗和註銷
- Token接口:用於客戶端調用,經過受權碼換取受權令牌
- Web filter:獲取請求中的受權令牌並校驗,若合法則經過請求,不然返回錯誤消息。
圖中有兩種應用類型,web應用和移動應用,兩種獲取受權方式基本同樣。
對於web應用,整個流程交互以下,
- 用戶經過瀏覽器訪問Web服務
- 後端服務中一個通用的web filter校驗請求,若發現請求中沒有受權令牌,則跳轉至第三方用戶登陸服務
- 在第三方登陸服務中,用戶輸入用戶名和密碼,若登陸成功,則跳轉回web應用,並返回受權碼
- Web應用將獲取到的受權碼,調用後端Token接口,該接口將根據受權碼+應用ID+應用Secret,向第三方申請受權令牌,若一切正常,第三方頒發受權令牌給Web應用,Web應用將獲取到的受權令牌存儲在瀏覽器的cookie中。
- 將用戶跳轉回用戶的初始訪問頁面,此時請求中cookie將自動帶上受權令牌
- 後端服務的web filter校驗請求cookie中的受權令牌,若合法且有效,則用戶能夠正常訪問後端服務,不然返回錯誤消息,提示用戶再次登陸。
- 用戶註銷登陸時,web應用服務將存儲在瀏覽器cookie中的受權令牌清除,並註銷redis中的令牌。
移動應用和web應用的流程相似,整個流程交互以下,
- 用戶打開移動應用,應用提示用戶登陸,並將用戶導向第三方登陸服務
- 在第三方登陸服務中,用戶輸入用戶名和密碼,若登陸成功,則跳轉回移動應用,並返回受權碼給移動應用。
- 移動應用將獲取到的受權碼,調用後端Token接口,該接口將根據受權碼+應用ID+應用Secret,向第三方申請受權令牌,若一切正常,第三方頒發受權令牌給移動應用,移動應用將獲取到的受權令牌存儲在手機上的應用存儲空間。
- 進入應用後,移動應用訪問後端服務,受權令牌攜帶在請求header中
- 後端服務中一個通用的web filter對請求header中的受權令牌進行校驗,若合法且有效,則用戶能夠正常訪問後端服務,不然提示用戶登陸。
- 用戶註銷登陸時,移動應用將受權令牌清除,並註銷redis中的令牌。
2.5 第一方登陸和第三方登陸的受權區別
第一方登陸和第三方登陸之間最大的區別在於受權流程。
第一方登陸在用戶被認證以後,即刻頒發受權令牌,應用服務通常無需介入受權流程。而第三方登陸在用戶認證以後,先頒發給受權碼給應用服務,應用服務還需根據這個受權碼去換取受權令牌,換句話說,應用服務需介入受權流程。
這裏有個問題是,爲何在第三方登陸中,應用服務會被介入受權流程?主要緣由是在第三方登陸場景中,除了用戶須要被認證,應用服務自己也須要被認證。而在第一方登陸場景,只需用戶認證,應用服務自己是可信的,其無需被認證。
2.6 登陸架構實現小結
爲了對比上述兩個登陸架構實現的不一樣之處,下面將各自的特色小結爲下表,
第一方登陸架構 | 第三方登陸架構 | |
---|---|---|
登陸功能 | 由己方提供 | 由第三方提供 使用第三方的用戶帳戶 |
登陸實現 | 經過http basic auth | OAuth 2.0受權碼模式 |
應用是否可信 | 可信,應用能夠接觸用戶密碼等敏感信息,應用自己無需認證 | 不可信 |
應用是否須要認證 | 否 | 是 |
應用是否能夠接觸用戶密碼等敏感信息 | 是 | 否 |
受權過程 | 登陸成功後頒發token | 1. 登陸成功後返回受權碼給應用 2. 應用根據受權碼和應用ID換取token |
Web頁面的服務請求 | 經過cookie帶上token | 經過cookie帶上token |
移動應用的服務請求 | 經過header帶上token | 經過header帶上token |
3. 權限控制
在互聯網應用開發中,安全控制在後端服務中實現。整個權限控制的過程通常會涉及到鑑權和權限控制兩個環節。
鑑權的實現方式通常有兩種,
- 經過受權服務器:因爲受權令牌是由受權服務器頒發的,因此由受權服務器校驗也是天然而然的事情。這種方式會致使受權服務器的訪問熱點問題,爲了緩解熱點,緩存是必要配置。
- 經過加解密:經過受權令牌的加解密方式,確認令牌的合法性。即,受權服務器頒發一個經過公鑰加密的受權令牌,在校驗的時候若可以經過私鑰解密,則該令牌爲合法令牌。這種方式有一個缺點是,一旦令牌註銷失效後,信息沒法及時通知到解密方。對令牌的註銷時效性要求不高的場景下,可使用這種方式,其大大緩解了受權服務器的訪問熱點問題。
若根據鑑權的架構方式,則可分爲分佈式和集中式兩大類,
- 分佈式:經過後端web服務的filter實現分佈式控制,在各個服務應用的運行實例中進行鑑權
- 集中式:經過網關實現集中式控制,在訪問流量的入口進行鑑權
鑑權後訪問控制粒度從大到小有以下三種分類,
- Http方法級別
- API接口級別
- API實現級別
下面將對鑑權的架構實現和控制粒度進行詳細討論。
3.1 分佈式鑑權架構
分佈式鑑權的架構以下圖,
在web應用開發中,能夠經過web應用服務的filter功能,對全部請求中的受權令牌進行校驗,實現分佈式鑑權。分佈式鑑權實現簡單,能夠快速實現並使用,但隨着應用服務架構的水平和垂直擴展,filter的升級將會成爲頭痛的問題。
3.2 集中式鑑權架構
集中式鑑權的架構以下圖,
經過網關,在訪問流量的入口,對全部請求中的受權令牌進行校驗,實現集中式鑑權。集中式鑑權減輕了應用服務的接入成本,但會增長了網關的性能負荷。
3.3 分佈式和集中式鑑權的優缺點
分佈式鑑權和集中式鑑權有各自的優缺點小結爲下表,
分佈式鑑權 | 集中式鑑權 | |
---|---|---|
優勢 | 簡單,能夠分散校驗熱點 | 應用服務接入成本低,方便鑑權管理 |
缺點 | filter版本升級困難,須要對全部應用服務進行依賴更新 | 須要網關的支持,而且鑑權操做將增長網關的性能負荷 |
應用場景 | 簡單的互聯網web應用開發 | 大型互聯網web應用開發 |
3.4 訪問控制的粒度
鑑權後就會獲得請求訪問的權限,接下來則是根據權限來控制請求訪問的容許或禁止。
根據訪問控制粒度從大到小,可劃分出以下幾個控制級別,
- Http方法級別
- API接口級別
- API實現級別
3.4.1 HTTP方法級別
若web應用服務是按照Restful的規範來開發接口服務,則能夠根據Restful的定義對Http的不一樣方法實現不一樣的訪問控制。
根據Restful的規範定義,Http方法具備以下安全性和冪等性的特色,
HTTP方法 | Restful定義 | 安全性 | 冪等性 |
---|---|---|---|
GET | 獲取資源 | 是 | 是 |
POST | 建立資源 | 否 | 否 |
PUT | 更新資源 | 否 | 是 |
DELETE | 刪除資源 | 否 | 是 |
HEADER | 資源元信息 | 是 | 是 |
OPTIONS | 是 | 是 |
表中,安全性和冪等性的概念以下,
- 安全性是指該方法不改變資源的狀態,即不改變後臺數據
- 冪等性是指該方法執行的同一操做屢次,其結果保持一致
能夠看到,對於安全的HTTP方法,好比GET操做,其訪問控制能夠寬鬆。而對於一些非安全操做,則須要根據不一樣權限來控制訪問請求。在實際應用過程當中,能夠執行以下的權限控制規則,
- 匿名用戶:能夠執行GET請求
- 普通登陸用戶:能夠執行GET、POST、PUT請求
- 管理員:能夠執行全部類別請求
總的來講,根據Http請求的方法和URI進行訪問控制。
3.4.2 API接口級別
這個權限控制的粒度深刻到代碼控制層(Controller),不一樣的權限,能夠訪問不一樣的API接口。
一個spring mvc的代碼樣例以下,
@Controller public class TokenApp { @PreAuthorize("hasAuthority('ROLE_ADMIN')") public Principal getUserInfo(Principal me){ return me; } }
上面的代碼表示,具備管理員角色的權限才能獲取當前用戶信息。
這個粒度的權限訪問控制基本能夠知足大多數應用場景需求。
3.4.3 API實現級別
在應用的實現級別進行控制,這個控制粒度很是細,其根據不一樣權限返回不同的調用結果,例如,一樣是查看學生列表,如果班主任,則返回一個班的學生列表,如果校長,則返回一個學校的學生列表。
4. 小結
本文主要從用戶登陸和權限控制兩大功能方面梳理其架構實現,這些實現能夠結合實際的應用場景,進行相應的匹配。
第一方登陸 | 第三方登陸 | |
---|---|---|
分佈式權限控制 | 1. 簡單web應用場景 2. 登陸服務和應用服務相互可信 3. 登陸服務和應用服務同域,能夠受權共享 |
1. 簡單web應用場景 2. 登陸服務和應用服務相互不可信 3. 登陸服務和應用服務不一樣域,各自獨立開發部署,沒法受權共享 4. 應用和登陸服務模塊完全解耦,經過跨域跳轉實現用戶登陸。 |
集中式權限控制 | 1. 大型web應用場景,有網關組件部署 | 1. 大型web應用場景,有網關組件部署 2. 快速接入第三方用戶 |