API:認證、授權(quán)、憑證

2 評論 20616 瀏覽 131 收藏 26 分鐘

以往講使用 spring security 等具體技術(shù)的資料已經(jīng)很多了,筆者這篇文章不打算寫框架和代碼的具體實現(xiàn),而是會討論認證和授權(quán)的區(qū)別。然后會介紹一些被業(yè)界廣泛采用的技術(shù),最后會聊聊:怎么為 API 構(gòu)建選擇合適的認證方式?

在一些互聯(lián)網(wǎng)公司的面試中,面試官往往會問這樣一個問題:“如果禁用瀏覽器 cookie,如何實現(xiàn)用戶追蹤和認證?”

遺憾的是:依然有大量候選人答非所問,無法搞清楚 cookie 和 session 之間的區(qū)別。

而在工作中也有讓人驚訝的真實案例:把 user ID 存儲到 local storage 中當做 token 使用,原因是他們聲稱棄用了 cookie 這種落后的東西;一個移動端項目,服務(wù)器給出的 API 中需要客戶端模擬一個 cookie,從而像瀏覽器中 ajax 那樣消費 API。

互聯(lián)網(wǎng)是基于 HTTP 協(xié)議構(gòu)建的,而 HTTP 協(xié)議因為簡單流行開來,但是 HTTP 協(xié)議是無狀態(tài)(通信層面上虛電路比數(shù)據(jù)報昂貴太多)的。為此人們?yōu)榱俗粉櫽脩粝氤隽烁鞣N辦法,包括 :cookie/session 機制、token、flash 跨瀏覽器 cookie 甚至瀏覽器指紋等。

細說API – 認證、授權(quán)和憑證

把用戶身份藏在每一個地方(瀏覽器指紋技術(shù)甚至不需要存儲介質(zhì))

認證、授權(quán)、憑證

首先,認證和授權(quán)是兩個不同的概念,為了讓我們的 API 更加安全和具有清晰的設(shè)計,理解認證和授權(quán)的不同就非常有必要了,它們在英文中也是不同的單詞。

細說API – 認證、授權(quán)和憑證

認證:是 authentication,指的是當前用戶的身份——當用戶登陸過后系統(tǒng)便能追蹤到他的身份做出符合相應(yīng)業(yè)務(wù)邏輯的操作。

即使用戶沒有登錄,大多數(shù)系統(tǒng)也會追蹤他的身份,只是當做來賓或者匿名用戶來處理。認證技術(shù)解決的是 “我是誰?”的問題。

授權(quán):與認證不同,授權(quán)是 authorization,指的是什么樣的身份被允許訪問某些資源,在獲取到用戶身份后繼續(xù)檢查用戶的權(quán)限。

單一的系統(tǒng)授權(quán)往往是伴隨認證來完成的,但是在開放 API 的多系統(tǒng)結(jié)構(gòu)下,授權(quán)可以由不同的系統(tǒng)來完成,例如 OAuth。授權(quán)技術(shù)是解決“我能做什么?”的問題。

實現(xiàn)認證和授權(quán)的基礎(chǔ)是需要一種媒介(credentials)來標記訪問者的身份或權(quán)利,在現(xiàn)實生活中每個人都需要一張身份證才能訪問自己的銀行賬戶、結(jié)婚和辦理養(yǎng)老保險等,這就是認證的憑證。

在古代軍事活動中,皇帝會給出戰(zhàn)的將軍頒發(fā)兵符,下級將領(lǐng)不關(guān)心持有兵符的人,只需要執(zhí)行兵符對應(yīng)的命令即可。在互聯(lián)網(wǎng)世界中,服務(wù)器為每一個訪問者頒發(fā) session ID 存放到 cookie,這就是一種憑證技術(shù)。

數(shù)字憑證還表現(xiàn)在方方面面:SSH 登錄的密匙、JWT 令牌、一次性密碼等。

用戶賬戶也不一定是存放在數(shù)據(jù)庫中的一張表,在一些企業(yè) IT 系統(tǒng)中,對賬戶管理和權(quán)限有了更多的要求。所以,賬戶技術(shù) (accounting)可以幫助我們使用不同的方式管理用戶賬戶,同時具有不同系統(tǒng)之間共享賬戶的能力,例如:微軟的活動目錄(AD),以及簡單目錄訪問協(xié)議(LDAP),甚至區(qū)塊鏈技術(shù)。

還有一個重要的概念是:訪問控制策略(AC)。如果我們需要把資源的權(quán)限劃分到一個很細的粒度,就不得不考慮用戶以何種身份來訪問受限的資源,選擇基于訪問控制列表(ACL)還是基于用戶角色的訪問控制(RBAC)或者其他訪問控制策略。

在流行的技術(shù)和框架中,這些概念都無法孤立的被實現(xiàn),因此在現(xiàn)實中使用這些技術(shù)時,大家往往為一個 OAuth2 是認證還是授權(quán)這種概念爭論不休。

為了容易理解,我在文末附上了一份常見技術(shù)和概念的術(shù)語表。

下面,我會介紹在API開發(fā)中常常使用的幾種認證和授權(quán)技術(shù):HTTP Basic AUthentication、HAMC、OAuth2,以及憑證技術(shù)JWT token。

HTTP Basic Authentication

你一定用過這種方式,但不一定知道它是什么。

在不久之前,當你訪問一臺家用路由器的管理界面,往往會看到一個瀏覽器彈出表單,要求你輸入用戶密碼。

細說API – 認證、授權(quán)和憑證

在這背后,當用戶輸入完用戶名密碼后,瀏覽器幫你做了一個非常簡單的操作:

  1. 組合用戶名和密碼然后 Base64 編碼。
  2. 給編碼后的字符串添加 Basic 前綴,然后設(shè)置名稱為 Authorization 的 header 頭部。

細說API – 認證、授權(quán)和憑證

API 也可以非常簡單的提供 HTTP Basic Authentication 認證方式,那么客戶端可以很簡單通過 Base64 傳輸用戶名和密碼即可:。

  1. 將用戶名和密碼使用冒號連接,例如 :username:abc123456。
  2. 為了防止用戶名或者密碼中存在超出 ASCII 碼范圍的字符,推薦使用UTF-8編碼。
  3. 將上面的字符串使用 Base 64 編碼,例如:dXNlcm5hbWU6YWJjMTIzNDU2。
  4. 在 HTTP 請求頭中加入 “Basic + 編碼后的字符串”——即:Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l。

這種方式實現(xiàn)起來非常簡單,在大量場景下被采用。

當然缺點也很明顯,Base64 只能稱為編碼,而不是加密 (實際上,無需配置密匙的客戶端并沒有任何可靠地加密方式,我們都依賴 TSL 協(xié)議)。

這種方式的致命弱點是:編碼后的密碼,如果明文傳輸則容易在網(wǎng)絡(luò)傳輸中泄露,在密碼不會過期的情況下,密碼一旦泄露,只能通過修改密碼的方式。

HMAC(AK/SK)認證

在我們對接一些 PASS 平臺和支付平臺時,會要求我們預(yù)先生成一個 access key(AK) 和 secure key(SK),然后通過簽名的方式完成認證請求。這種方式可以避免傳輸 secure key,且大多數(shù)情況下簽名只允許使用一次,避免了重放攻擊。

這種基于 AK/SK 的認證方式主要是利用散列的消息認證碼 (Hash-based MessageAuthentication Code) 來實現(xiàn)的。因此,有很多地方叫 HMAC 認證,實際上不是非常準確。

HMAC 只是利用帶有 key 值的哈希算法生成消息摘要,在設(shè)計 API 時有具體不同的實現(xiàn)。

細說API – 認證、授權(quán)和憑證

HMAC 在作為網(wǎng)絡(luò)通信的認證設(shè)計中作為憑證生成算法使用,避免了口令等敏感信息在網(wǎng)絡(luò)中傳輸。

基本過程如下:

  1. 客戶端需要在認證服務(wù)器中預(yù)先設(shè)置 access key(AK 或叫 app ID) 和 secure key(SK)。
  2. 在調(diào)用 API 時,客戶端需要對參數(shù)和 access key 進行自然排序后并使用 secure key 進行簽名生成一個額外的參數(shù) digest。
  3. 服務(wù)器根據(jù)預(yù)先設(shè)置的 secure key 進行同樣的摘要計算,并要求結(jié)果完全一致。
  4. 注意 secure key 不能在網(wǎng)絡(luò)中傳輸,以及在不受信任的位置存放(瀏覽器等)。

為了讓每一次請求的簽名變得獨一無二,從而實現(xiàn)重放攻擊,我們需要在簽名時放入一些干擾信息。

在業(yè)界標準中有兩種典型的做法,質(zhì)疑/應(yīng)答算法(OCRA: OATH Challenge-Response Algorithm)、基于時間的一次性密碼算法(TOTP:Time-based One-time Password Algorithm)。

1. 質(zhì)疑/應(yīng)答算法

質(zhì)疑/應(yīng)答算法需要客戶端先請求一次服務(wù)器,獲得一個 401 未認證的返回,并得到一個隨機字符串(nonce)。

將 nonce 附加到按照上面說到的方法進行 HMAC 簽名,服務(wù)器使用預(yù)先分配的 nonce 同樣進行簽名校驗,這個 nonce 在服務(wù)器只會被使用一次,因此可以提供唯一的摘要。

細說API – 認證、授權(quán)和憑證

2. 基于時間的一次性密碼認證

為了避免額外的請求來獲取 nonce,還有一種算法是使用時間戳,并且通過同步時間的方式協(xié)商到一致,在一定的時間窗口內(nèi)有效(1分鐘左右)。

細說API – 認證、授權(quán)和憑證

這里的只是利用時間戳作為驗證的時間窗口,并不能嚴格的算作基于時間的一次性密碼算法。

標準的基于時間的一次性密碼算法在兩步驗證中被大量使用,例如:Google 身份驗證器不需要網(wǎng)絡(luò)通信也能實現(xiàn)驗證(但依賴準確的授時服務(wù))。

原理是:客戶端服務(wù)器共享密鑰然后根據(jù)時間窗口能通過 HMAC 算法計算出一個相同的驗證碼。

細說API – 認證、授權(quán)和憑證

TOTP 基本原理和常見廠商

OAuth2 和 Open ID

OAuth(開放授權(quán))是一個開放標準,允許用戶授權(quán)第三方網(wǎng)站訪問他們存儲在另外的服務(wù)提供者上的信息,而不需要將用戶名和密碼提供給第三方網(wǎng)站或分享他們數(shù)據(jù)的所有內(nèi)容。

OAuth 是一個授權(quán)標準,而不是認證標準。提供資源的服務(wù)器不需要知道確切的用戶身份(session),只需要驗證授權(quán)服務(wù)器授予的權(quán)限(token)即可。

細說API – 認證、授權(quán)和憑證

上圖只是 OAuth 的一個簡化流程,OAuth 的基本思路就是通過授權(quán)服務(wù)器獲取 access token 和 refresh token(refresh token 用于重新刷新access token),然后通過 access token 從資源服務(wù)器獲取數(shù)據(jù) 。

在特定的場景下還有下面幾種模式:

  1. 授權(quán)碼模式(authorization code)
  2. 簡化模式(implicit)
  3. 密碼模式(resource owner password credentials)
  4. 客戶端模式(client credentials)

如果需要獲取用戶的認證信息,OAuth 本身沒有定義這部分內(nèi)容,如果需要識別用戶信息,則需要借助另外的認證層,例如: OpenID Connect。

1. 驗證 access token

在一些介紹OAuth 的博客中,很少講到:資源服務(wù)器是怎么驗證 access token 的?

OAuth core 標準并沒有定義這部分,不過在 OAuth 其他標準文件中提到兩種驗證 access token的方式。

1)在完成授權(quán)流程后,資源服務(wù)器可以使用 OAuth 服務(wù)器提供的 Introspection 接口來驗證access token,OAuth服務(wù)器會返回 access token 的狀態(tài)以及過期時間。

在OAuth標準中驗證 token 的術(shù)語是 Introspection。同時,也需要注意 access token 是用戶和資源服務(wù)器之間的憑證,不是資源服務(wù)器和授權(quán)服務(wù)器之間的憑證。資源服務(wù)器和授權(quán)服務(wù)器之間應(yīng)該使用額外的認證(例如:Basic 認證)。

2)使用 JWT 驗證:授權(quán)服務(wù)器使用私鑰簽發(fā) JWT 形式的 access token,資源服務(wù)器需要使用預(yù)先配置的公鑰校驗 JWT token,并得到 token 狀態(tài)和一些被包含在 access token 中信息。因此,在 JWT 的方案下,資源服務(wù)器和授權(quán)服務(wù)器不再需要通信,在一些場景下帶來巨大的優(yōu)勢。同時,JWT 也有一些弱點,我會在JWT 的部分解釋。

2. refresh token 和 access token

幾乎所有人剛開始了解 OAuth 時都有一個一疑問:為什么已經(jīng)有了 access token 還需要 refresh token 呢?

授權(quán)服務(wù)器會在第一次授權(quán)請求時,一起返回 access token 和refresh token,在后面刷新 access token 時只需要 refresh token。

access token 和 refresh token 的設(shè)計意圖是不一樣的,access token 被設(shè)計用來客戶端和資源服務(wù)器之間交互,而 refresh token 是被設(shè)計用來客戶端和授權(quán)服務(wù)器之間交互。

某些授權(quán)模式下, access token 需要暴露給瀏覽器,充當一個資源服務(wù)器和瀏覽器之間的臨時會話,瀏覽器和資源服務(wù)器之間不存在簽名機制,access token 成為唯一憑證。因此,access token 的過期時間(TTL)應(yīng)該盡量短,從而避免用戶的 access token 被嗅探攻擊。

由于要求 access token 時間很短,refresh token 可以幫助用戶維護一個較長時間的狀態(tài),避免頻繁重新授權(quán)。

大家會覺得讓 access token 保持一個長的過期時間不就可以了嗎?

實際上,refresh token 和 access token 的不同之處在于:即使 refresh token 被截獲,系統(tǒng)依然是安全的,客戶端拿著 refresh token 去獲取 access token 時,同時需要預(yù)先配置的 secure key,客戶端和授權(quán)服務(wù)器之前始終存在安全的認證。

3. OAuth、Open ID、OpenID Connect

認證方面的術(shù)語實在太多,我在搭建自己的認證服務(wù)器或接入第三方認證平臺時,有時候到完成開發(fā)工作的最后一刻都無法理解這些術(shù)語。

OAuth 負責(zé)解決分布式系統(tǒng)之間的授權(quán)問題,即使有時候客戶端和資源服務(wù)器或者認證服務(wù)器存在同一臺機器上。OAuth 沒有解決認證的問題,但提供了良好的設(shè)計利于和現(xiàn)有的認證系統(tǒng)對接。

Open ID 解決的問題是:分布式系統(tǒng)之間身份認證問題,使用Open ID token 能在多個系統(tǒng)之間驗證用戶,以及返回用戶信息,可以獨立使用,與 OAuth 沒有關(guān)聯(lián)。

OpenID Connect 解決的是:在 OAuth 這套體系下的用戶認證問題,實現(xiàn)的基本原理是將用戶的認證信息(ID token)當做資源處理。在 OAuth 框架下完成授權(quán)后,再通過 access token 獲取用戶的身份。

這三個概念之間的關(guān)系有點難以理解,用現(xiàn)實場景來說:如果系統(tǒng)中需要一套獨立的認證系統(tǒng),并不需要多系統(tǒng)之間的授權(quán)可以直接采用 Open ID。

如果使用了 OAuth 作為授權(quán)標準,可以再通過 OpenID Connect 來完成用戶的認證。

JWT

在 OAuth 等分布式的認證、授權(quán)體系下,對憑證技術(shù)有了更多的要求,比如:包含用戶 ID、過期等信息,不需要再外部存儲中關(guān)聯(lián)。

因此,業(yè)界對 token 做了進一步優(yōu)化,設(shè)計了一種自包含令牌,令牌簽發(fā)后無需從服務(wù)器存儲中檢查是否合法,通過解析令牌就能獲取令牌的過期、有效等信息,這就是JWT (JSON Web Token)。

JWT 是一種包含令牌(self-contained token),或者叫值令牌 (value token),我們以前使用關(guān)聯(lián)到 session 上的 hash 值被叫做引用令牌(reference token)。

細說API – 認證、授權(quán)和憑證

簡而言之,一個基本的JWT令牌為一段點分3段式結(jié)構(gòu)。

生成JWT 令牌的流程為:

細說API – 認證、授權(quán)和憑證

  1. header json 的 base64 編碼為令牌第一部分。
  2. payload json 的 base64 編碼為令牌第二部分。
  3. 拼裝第一、第二部分編碼后的 json 以及 secret 進行簽名的令牌的第三部分。

因此,只需要簽名的 secret key 就能校驗 JWT 令牌,如果在消息體中加入用戶 ID、過期信息就可以實現(xiàn)驗證令牌是否有效、過期了,無需從數(shù)據(jù)庫/緩存中讀取信息。因為使用了加密算法,所以第一、二部分即使被修改(包括過期信息)也無法通過驗證。

JWT 優(yōu)點是:不僅可以作為 token 使用,同時也可以承載一些必要信息,省去多次查詢。

注意:

  1. JWT token 的第一、二部分只是 base64 編碼,肉眼不可讀,不應(yīng)當存放敏感信息。
  2. JWT token 的自包含特性,導(dǎo)致了無法被撤回。
  3. JWT 的簽名算法可以自己擬定,為了便于調(diào)試,本地環(huán)境可以使用對稱加密算法,生產(chǎn)環(huán)境建議使用非對稱加密算法。

JWT token 在微服務(wù)的系統(tǒng)中優(yōu)勢特別突出:多層調(diào)用的 API 中可以直接傳遞 JWT token,利用自包含的能力,可以減少用戶信息查詢次數(shù);更重要的是,使用非對稱的加密方式可以通過在系統(tǒng)中分發(fā)密匙的方式驗證 JWT token。

當然,OAuth 對 access token 等憑證所選用的技術(shù)并沒有做出限制,OAuth 并不強制使用 JWT,在使用 JWT 自包含特性的優(yōu)勢時,必須考慮到 JWT 撤回困難的問題。在一些對撤回 token 要求很高的項目中不適合使用JWT,即使采用了一些方案實現(xiàn)(whitelist 和 blacklist)也違背了設(shè)計 JWT 的初衷。

Cookie 、Token in Cookie、Session Token 依然被使用

在構(gòu)建 API 時,開發(fā)者會發(fā)現(xiàn)我們的認證方式和網(wǎng)頁應(yīng)用有一些不同,除了像 ajax 這種典型的 web 技術(shù)外,如果我們希望 API 是無狀態(tài)的,不推薦使用 Cookie。

使用 Cookie 的本質(zhì)是用戶第一次訪問時服務(wù)器會分配一個 Session ID,后面的請求中客戶端都會帶上這個 ID 作為當前用戶的標志。因為 HTTP 本身是無狀態(tài)的,Cookie 屬于一種內(nèi)建于瀏覽器中實現(xiàn)狀態(tài)的方式。如果我們的 API 是用來給客戶端使用的,強行要求 API 的調(diào)用者管理Cookie 也可以完成任務(wù)。

在一些遺留或者不是標準的認證實現(xiàn)的項目中,我們依然可以看到這些做法,快速地實現(xiàn)認證。

  1. 使用 cookie,例如 web 項目中 ajax 的方式。
  2. 使用 session ID 或 hash 作為 token,但將 token 放入 header 中傳遞。
  3. 將生成的 token (可能是JWT)放入 cookie 傳遞,利用 HTTPonly 和 Secure 標簽保護 token。

選擇合適的認證方式

隨著微服務(wù)的發(fā)展,API 的設(shè)計不僅僅是面向 WEB 或者 Mobile APP,還有BFF(Backend for Frontend)和 Domain API 的認證,以及第三方服務(wù)的集成。

客戶端到服務(wù)器之間認證和服務(wù)器到服務(wù)器之間認證是不同的。

我們把終端用戶(Human)參與的通信,叫做 Human-to-machine (H2M),服務(wù)器與服務(wù)器之間的通信叫做 Machine-to-machine (M2M)。

H2M 的通信需要更高的安全性,M2M 的通信天然比 H2M 安全,因此更多的強調(diào)性能,在不同的場合下選擇合適的認證技術(shù)就顯得特別重要。例如: HTTP Basic Authentication 用來作為 H2M 認證顯得有些落后,但是在 M2M 中被大量使用。

另外值得一提的是:H2M 這種通信方式下,客戶端不受控制,由于無法自主分發(fā)密匙,認證通信的安全高度依賴 HTTPS。

從一個宏觀的角度看待他們的關(guān)系,對我們技術(shù)選型非常有幫助。

細說API – 認證、授權(quán)和憑證

術(shù)語表

  1. Browser fingerprinting 通過查詢?yōu)g覽器的代理字符串,屏幕色深,語言等,然后這些值通過散列函數(shù)傳遞產(chǎn)生指紋,不需要通過 Cookie 就可以識別瀏覽器。
  2. MAC(Message authentication code) 在密碼學(xué)中,訊息鑒別碼,是經(jīng)過特定算法后產(chǎn)生的一小段資訊,檢查某段訊息的完整性。
  3. HOTP(HMAC-based One-time Password algorithm)基于散列消息驗證碼的一次性密碼算法。
  4. Two-step verification 是一種認證方法,使用兩種不同的元素,合并在一起,來確認使用者的身份,是多因素驗證中的一個特例。
  5. OTP (One time password )一次性密碼,例如注冊郵件和短信中的認證碼。

參考文章

https://swagger.io/docs/specification/authentication/basic-authentication/

[HMAC: Keyed-Hashing for Message Authentication]( “https://www.ietf.org/rfc/rfc2104.txt “)

HOTP: An HMAC-Based One-Time Password Algorithm

OCRA: OATH Challenge-Response Algorithm

The OAuth 2.0 Authorization Framework

JSON Web Token (JWT)

OAuth 2.0

Internet-Draft Archive for OAuth

 

作者:ThoughtWorks林寧,微信公眾號:ThoughtWorks洞見

本文由@ThoughtWorks林寧 原創(chuàng)發(fā)布于人人都是產(chǎn)品經(jīng)理,未經(jīng)允許,禁止轉(zhuǎn)載。

題圖來自Unsplash, 基于CC0協(xié)議

更多精彩內(nèi)容,請關(guān)注人人都是產(chǎn)品經(jīng)理微信公眾號或下載App
2021亚洲中文字幕在线第99,日韩一级无码国产精品,日韩精品无码一级毛片免费丿,免费在线观看毛片黄片