學習Identity Server 4的預備知識 (誤刪, 重補)

solenovex發表於2018-08-02

我要使用asp.net core 2.0 web api 搭建一個基礎框架並立即應用於一個實際的專案中去.

這裡需要使用identity server 4 做單點登陸.

下面就簡單學習一下相關的預備知識.

基於Token的安全驗證體系

這個比較簡單, 簡單來說就是為了證明我們有訪問許可權, 我們首先需要獲得一個token.

什麼是token? 比如說: 可以訪問某些大樓的門禁卡就是一種token, 回家開門的鑰匙也是一種token.

為了獲取到token, 首先你需要驗證你的身份, 以證明你確實有權利獲得token. 比如說, 你可以亮出身份證來證明自己, 或者使用密碼.

比如說你想訪問我的辦公室, 你首先去安全部門亮出身份證, 然後安全辦公室給你一個token, 然後使用這個token你就可以進入辦公室去幹事了.

使用基於token的安全體系有什麼優點?

如果不使用token, 你可能需要到處使用密碼來證明身份. 這樣的話, 那每個地方都會知道你的密碼了.

如果token丟失了, 我們可以吊銷token.

並且token都有一定的時效性. 過期作廢

總之, 使用這種方式, 你可以只在一個地方使用密碼, 別的地方不會知道你的密碼.

交換憑證獲取token並使用token

有一個已註冊使用者, 她為了獲取token, 就需要與authorization server進行通訊. 這個authorization server負責發放token, 並且確保token是否仍然有效. 它同時也負責跟蹤使用者的使用者名稱和密碼. 而這個authorization server可以存在於世界的任何地方, 它並不是非得和我們的web api或者網站放在一起. 它完全是一個獨立的系統, 跟蹤著使用者的使用者名稱密碼以及使用者的訪問許可權.

這裡這個使用者就向authorization server提供了使用者名稱和密碼, 然後她就獲得了token. 然後她就可以使用這個token做一些事情了, 比如使用token訪問api請求所有的訂單資訊, 這時api就會知道這個token是有效的.

甚至, 使用者使用token可以訪問第三方服務, 第三方服務再使用這個token來訪問我們的api.

向第三方服務提供token肯定比提供使用者名稱密碼安全多了.

要把Token向密碼一樣對待

保護好token, 因為別人獲得token後將會和你擁有一樣的許可權.

token是有時效性的, 具體有效期是多久是由authorization server決定的.

token是可以吊銷的, 你可以告訴authorization server登出你的token, 但是要注意的是, 是由api決定是否向authorization server查詢token的有效性, 如果你吊銷token或api沒有向authorization server進行查詢, 那麼你的token對api來說依然有效.

如何保證token的安全

如圖, 使用者帶著token向api發出請求, token是附帶在header中, api收到請求後會返回一些資料.

如果有人檢視了這個token, 並要篡改token裡面的資料, 那可就不好了

那麼如何保證token不被篡改呢? 這個工作是由api來做的, 它要確保沒人篡改過token.

在基於token驗證的情景中, 所有從authorization server獲取的token都是使用一個private key簽過名的. token包括一些資訊: 使用者本身(email, 許可權等等), 也可能包括是誰釋出了token.

任何一個服務想確定沒人篡改過token, 就需要使用public key.

private key 可以用於鎖定 token.

針對token和它帶的資料以及在token尾部的簽名資訊, 只要沒人篡改資料, 那麼token的簽名就是一定的.

authorization server提供的public key是任何人都可以訪問的, public key是用來確保沒人篡改過資料.

Token

如果在api裡面驗證了token的完整性, 那麼我們就會知道token是ok的.

我們這裡研究的token是Json Web Token.

token是由authorization server簽名釋出的.

authorization server就是使用oauth和openid connect等協議, 並且使用者可以使用使用者名稱密碼等方式來換取token的服務, 這些token讓我們擁有了訪問一些資源的許可權.

private key 是用來簽發token用的, 它只存在於authorization server, 永遠不要讓別人知道private key.

public key 是用來驗證token的, authorization server 會讓所有人都知道這個public key的.

api或者各種消費者應該一直檢驗token, 以確保它們沒有被篡改. 它們可以向authorization server申請public key, 並使用它來驗證token. 也可以把token傳遞給authorization server, 並讓authorization server來進行驗證.

Token同時也包含著authorization server的一些資訊. 比如是由哪個authorization server釋出的token.

Token的資訊是使用Base64編碼的.

OAuth 和 OpenId Connect

他們都是安全協議.

現在使用的都是OAuth 2.0, 注意它與1.0不相容.

OAuth 2.0是用於authorization的工業標準協議. 它關注的是為web應用, 桌面應用, 移動應用等提供特定的authorization流程並保證開發的簡單性.

Authorization的意思是授權, 它表示我們可以授權給某些使用者, 以便他們能訪問一些資料, 也就是提供訪問權.

OAuth是基於token的協議.

有些人可能對Authorization和Authentication分不清, 上面講了authorization, 而authentication則是證明我是誰, 例如使用使用者名稱和密碼進行登入就是authentication.

OAuth只負責Authorization. 那麼誰來負責Authentication呢?

那就是OpenId Connect, OpenId Connect是對OAuth的一種補充, 因為它能進行Authentication.

OpenId Connect 是位於OAuth 2.0上的一個簡單的驗證層, 它允許客戶端使用authorization server的authentication操作來驗證終端使用者的身份, 同時也可以或缺終端客戶的一些基本資訊.

可以有多種方式來實現OAuth和OpenId Connect這套協議.

你可以自己去實現. 

我要使用的是Identity Server 4.

其實也可以使用一些Saas/Paas服務, 例如Amazon Cognito, Auth0(這個用過, 有免費版), Stormpath.

OAuth 2.0 RFC 6794

想研究的比較透徹的話, 還是要多讀幾遍 RC 6749文件: https://tools.ietf.org/html/rfc6749

OAuth通常有以下幾種endpoint:

1. /authorize, 請求token(通過特定的流程flows)

2. /token, 請求token(通過特定的流程flows), 重新整理token, 使用authorization code來換取token.

3. /revocation, 吊銷token.

OpenId Connect 通常有以下幾種 endpoints:

1. /userinfo, 獲取使用者資訊

2. /checksession, 檢查當前使用者的session

3. /endsession, 終結當前使用者的session

4. /.well-known/openid-configuration, 提供了authorization server的資訊(endpoints列表和配置資訊等)

5. /.well-known/jwks, 列出了JWT簽名key的資訊, 它們是用來驗證token的.

獲取Token的例子:

使用postman大約是這樣傳送請求.

請求返回的結果大約是這樣的:

access_token就是token, expires_in是有效時間, 型別是 Bearer.

可以到jwt.io去解析token: http://jwt.io/

由於網路問題, 我今天無法使用這個網站.....以後做專案寫文章的時候再介紹. 這裡你可以試試把一個token的資料更改之後, token驗證就出錯了. 

下面這個圖是如何使用token訪問api:

Access Token (JWT)

紅色的是Header, 橘色的是Payload, 藍色的是簽名Signature. 它們是用.分開的

Signature主要是來保證Payload的完整性. Header包含了token的結構資訊.

Payload有時候也叫做Claims, 它通常包括髮布者issuer(authorization server), Audience, 有效期, 有時也包括token應該是從什麼時候開始有效, Client ID(這是那些註冊於authorization server的應用), Scopes(限定訪問的範圍), 自定義資料.

Scopes

scopes可以限定訪問的範圍.

OpenId Connect為我們指定了一些 Scopes, 包括: openid, profile, email, address, offline_access等等.

當然也可以自定義scope.

選擇一個流程 Flow

Redirect Flows, 它可以這樣解釋: 有一個使用者想要訪問我的網站, 我想讓他登入, 但又不想讓他把使用者名稱和密碼提供給我, 因為我沒有使用者的資訊. 使用者的資訊都在authorization server上了. 所以我把使用者重定向到authorization server, 提供他們的使用者名稱和密碼, 然後重定向返回到我的網站, 獲取了token, 這時我就知道他們已經登入好了.

 

Redirect Flows又分兩種: 1 Implicit Grant(就是上面說的那個), 2 Authorization Code(它並沒有返回token, 而是返回了authorization code, 而網站可以使用authorization code來換取token).

所以implicit grant適合於javascript客戶端, 而其他應用更適合使用authorization code, 這些應用可以使用authorization code重新整理token.

Credential Flows: 1.Resource Owner Password Credentials(使用者名稱密碼). 2. Client Credentials(例如適用於沒有使用者參與的情況).

相關文章