Restful安全認證及許可權的解決方案
一、Restful安全認證常用方式 1.Session+Cookie 傳統的Web認證方式。需要解決會話共享及跨域請求的問題。 2.JWT JSON Web Token。 3.OAuth 支援兩方和三方認證,是目前使用比較廣泛的安全認證方式,但對於不使用第三方登入的認證的方式不太適用。 二、JWT簡介 JWT由三部分組成,包括Header、Payload和Signature。
JSON Web Token example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJpc3MiOiJ0b3B0YWwuY29tIiwiZXhwIjoxNDI2NDIwODAwLCJodHRwOi8vdG9wdGFsLmNvbS9qd3RfY2xhaW1zL2lzX2FkbWluIjp0cnVlLCJjb21wYW55IjoiVG9wdGFsIiwiYXdlc29tZSI6dHJ1ZX0. yRQYnWzskCZUxPwaQupWkiUzKELZ49eM7oWxAQK_ZXw
Example Header:
{
“alg”: “HS256”,
“typ”: “JWT”
}
通過加密後得到:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 一般Payload包括以下幾方面內容: iss: The issuer of the token sub: The subject of the token aud: The audience of the token exp: Token expiration time defined in Unix time nbf: “Not before” time that identifies the time before which the JWT must not be accepted for processing iat: “Issued at” time, in Unix time, at which the token was issued jti: JWT ID claim provides a unique identifier for the JWT Example Payload:
{
“iss”: “toptal.com”,
“exp”: 1426420800,
“https://www.toptal.com/jwt_claims/is_admin”: true,
“company”: “Toptal”,
“awesome”: true
}
通過加密後得到: eyJpc3MiOiJ0b3B0YWwuY29tIiwiZXhwIjoxNDI2NDIwODAwLCJodHRwOi8vdG9wdGFsLmNvbS9qd3RfY2xhaW1zL2lzX2FkbWluIjp0cnVlLCJjb21wYW55IjoiVG9wdGFsIiwiYXdlc29tZSI6dHJ1ZX0 Example Signature: 通過金鑰對Header和Payload生成簽名。 JWT的優勢: 無狀態,可以無限水平擴充套件 可重用,可以在多語言多平臺多域中使用 安全性高,由於沒有使用Cookie,因此可以防止跨站請求偽造(CSRF)攻擊 效能好,只驗證令牌並解析其內容 三、JWT認證方式的實現方式 1.客戶端不需要持有金鑰,由服務端通過金鑰生成Token。 2.客戶端登入時通過賬號和密碼到服務端進行認證,認證通過後,服務端通過持有的金鑰生成Token,Token中一般包含失效時長和使用者唯一標識,如使用者ID,服務端返回Token給客戶端。 3.客戶端儲存服務端返回的Token。 4.客戶端進行業務請求時在Head的Authorization欄位裡面放置Token,如: Authorization: Bearer Token 5.服務端對請求的Token進行校驗,並通過Redis查詢Token是否存在,主要是為了解決使用者登出,但Token還在時效內的問題,如果Token在Redis中存在,則說明使用者已登出;如果Token不存在,則校驗通過。 6.服務端可以通過從Token取得的使用者唯一標識進行相關許可權的校驗,並把此使用者標識賦予到請求引數中,業務可通過此使用者標識進行業務處理。 7.使用者登出時,服務端需要把還在時效內的Token儲存到Redis中,並設定正確的失效時長。
四、在實際環境中如何使用JWT 1.Web應用程式 在令牌過期前重新整理令牌。如設定令牌的過期時間為一個星期,每次使用者開啟Web應用程式,服務端每隔一小時生成一個新令牌。如果使用者一個多星期沒有開啟應用,他們將不得不再次登入。 2.移動應用程式 大多數移動應用程式使用者只進行一次登入,定期重新整理令牌可以使使用者長期不用登入。 但如果使用者的手機丟失,則可提供一種方式由使用者決定撤銷哪個裝置的令牌。當然,這就需要服務端記錄裝置的名稱,例如“maryo的iPad”。然後使用者可以去申請並撤銷獲得“maryo的iPad”。當用戶修改密碼時需要服務端把原Token儲存到Redis上,使其失效。 為了防止Token被竊取,最好把JWT和HTTPS結合起來使用。 五、如何實現安全認證與許可權的結合 服務端生成的Token中需要包含使用者唯一標識,這樣使用者進行業務請求時,服務端通過附帶的Token獲取使用者唯一標識,通過此標識進行許可權檢查。 六、更換Token 為了解決高併發訪問時更換Token, 有可能造成用舊的Token的訪問失敗。 在快取中不儲存Token,而是儲存一個計數,每次更換Token時,計數加1,這個計數的值會跟使用者ID一起加密後儲存在新生成的Token中,返回給使用者,使用者每次訪問時攜帶這個Token。驗證使用者Token時,用Token中的計數與快取中儲存的計數比較,如果差值範圍在1~2之間就認為Token有效,這樣即使在併發訪問時,更換Token,計數值雖然不等,但在規定的差值範圍內,也被認為有效,這樣就解決了上面的Token失效問題。 七、附錄 https://www.toptal.com/web/cookie-free-authentication-with-json-web-tokens-an-example-in-laravel-and-angularjs http://stackoverflow.com/questions/26739167/jwt-json-web-token-automatic-prolongation-of-expiration http://www.haomou.net/2014/08/13/2014_web_token/ https://jwt.io/