1. 一些概念
-
單點登錄:html
- 一套公用的用戶體系,登錄後,可以訪問全部的系統。
- 這只是一類解決方案的統稱,在具體的實施方面,有兩種策略 SAML,OAuth
-
OpenID:web
- 好比,容許使用微信/支付寶或者其餘帳號 登錄 其餘網站
- 只用於身份認證,容許你以同一個帳號在多個網站登錄。
- 登錄後 ,該站點沒法訪問你在 微信 上的數據。
- Authentication:身份鑑別,也就是 認證(鑑別是否爲合法用戶)
- Authorisation:受權(鑑別訪問權限)
- SMAL 2.0: https://zhuanlan.zhihu.com/p/...
-
OAuth :算法
1. token 的典型流程:
- 用戶登陸的時候,服務端生成一個token(經過登陸信息作數字簽名,加密以後獲得的字符串)返回給客戶端
- 客戶端後續的請求都帶上這個token
- 服務端解析token(作解密和簽名認證,判斷其有效性)獲取用戶信息,並響應用戶的請求。
- token會有過時時間,客戶端登出的時候也會廢棄token,可是服務端不須要任何操做
2. session 和 token 的區別:
- session, 要求服務端存儲信息,並根據id可以檢索,而 token 不須要。
- 服務端 要 經過 token 來解析 用戶身份,也須要定義好相應的協議。
- session 通常使用cookie 來交互。token,能夠是 cookie,也能夠是 其餘heaser,甚至能夠放在請求的內容中。不使用cookie能夠帶來跨域的便利性
- 不少狀況下,sessin 和 token 能夠一塊兒使用。
- token 技術 對應的標準,就是JWT
3.JWT(JSON Web Tokens)
-
組成:數據庫
-
Header(頭部)(是一個JSON 對象)json
{
"alg": "HS256", // 表示簽名的算法,默認是 HMAC SHA256(寫成 HS256)
"typ": "JWT" // 表示Token的類型,JWT 令牌統一寫爲JWT
}
- Payload(負載)(也是一個JSON 對象-- 用來存放實際須要傳遞的數據)
{
// 7個官方字段
"iss": "a.com", // issuer:簽發人
"exp": "1d", // expiration time:(必須設置)
"sub": "test", // subject: 主題
"aud": "xxx", // audience: 受衆
"nbf": "xxx", // Not Before:生效時間
"iat": "xxx", // Issued At: 簽發時間
"jti": "1111", // JWT ID:編號
// 能夠定義私有字段
"name": "John Doe",
"admin": true
}
-
Signature(簽名)跨域
- 對前兩部分的簽名,防止數據被篡改。
- 須要指定一個密鑰(secret)。
-
採用的公式:安全
- header 中的簽名算法(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret)
- JWT = Base64(Header) + "." + Base64(Payload) + "." + $Signature
-
特色:服務器
- JWT 默認是不加密的,任何人均可以讀到,因此不要把祕密信息放在這個部分。
- 發送 JWT, 要使用 https,不實用HTTPS的時候,JWT裏面不要寫入祕密數據。
- 在使用過程當中沒法廢除 某個 token,或者更改 token 的權限,也就是一旦簽發就會始終有效。
-
使用方法:微信
- 客戶端,獲得 token 後,能夠存儲在 cookie裏,或者localstorage 中
- 之後的http 請求都要帶着 這個token
- 發送的時候:能夠放在cookie 中,也能夠放在 HTTP 請求頭 信息 Authorization 字段中,還能夠在 post 請求的時候放在請求數據體裏。
-
分類:cookie
-
access token:
-
refresh token:
- 有效期長。
- 自身以及過時時間是 存儲在服務器的數據庫中的。
- 只有在申請新的 access token 的之後纔會驗證,不會對業務接口響應時間形成影響,也不會一直保存在內存中以應對大量的請求。
-
爲何要有 refresh token?
- 目的:職能分離。refresh token 負責身份認證,access token 負責請求資源。
-
-
流程:
- client -> server: username && password
- server: 獲得token
- server -> client: access token 、 refresh token
- client:將 token保存在本地
- client -> server: access token
- server: access token 沒有過時
- server -> client: 返回數據
- client -> server: access token
- server: access token 過時
- server -> client: 返回錯誤
- client -> server: refresh token
- server: 判斷 refresh token 是否過時
- server -> client: 沒過時,則返回新 的 access token和 refresh token。若是過時了,須要從新登錄
4. token 和 session 的區別:
-
session:
- 爲無狀態的HTTP提供持久機制。
- 若是須要實現有狀態的會話,能夠增長Session來在服務端保存一些狀態。
- 只提供一種簡單的認證,數據只保存在站點,不該該共享給其餘網站或者第三方APP
-
token:
- 就是一個令牌。
- 做爲身份認證安全性更好。
- 若是你的用戶數據可能須要和第三方共享,或者容許第三方調用API接口,用Token。
5. bearer token:
-
定義:
- 用於 OAuth 2.0 受權訪問資源
- 任何 持有 bearer 的均可以訪問資源,而無需證實持有加密 key。
- 一個 bearer 表明受權範圍、有效期,以及其餘受權事項。
- 傳輸時,要防止泄露。
- 有效期不能過長,過時後,可以使用 refresh token 申請 更新。
-
資源請求:
- bearer 實現資源請求移動有 3種方式,如下的優先級依次遞減。
- Authorization Header:
Authorization: Bearer mF_9.B5f-4.1JqM
-
Form-Encoded Body Parameter:
Content-Type: application/x-www-form-urlencoded
access_token=mF_9.B5f-4.1JqM
-
使用條件:
- 頭部必須包含"Content-Type: application/x-www-form-urlencoded"
- entity-body必須遵循application/x-www-form-urlencoded編碼(RFC 6749)
- 若是entity-body除了access_token以外,還包含其餘參數,須以"&"分隔開
- entity-body只包含ASCII字符
- 要使用request-body已經定義的請求方法,不能使用GET
-
URI Query Parameter:
GET /resource?access_token=mF_9.B5f-4.1JqM HTTP/1.1
Cache-Control: no-store
- 服務端應在響應中使用 Cache-Control: private
-
WWW-Authenticate 頭:
- 在客戶端未發送有效Bearer的狀況下,即錯誤發生時,資源服務器鬚髮送WWW-Authenticate頭
- 例:
WWW-Authenticate: Bearer realm="example", error="invalid_token", error_description="The access token expired"
-
字段用法:
- Bearer:Beare做爲一種認證類型(基於OAuth 2.0),使用"Bearer"關鍵詞進行定義
- realm:與Basic、Digest同樣,Bearer也使用相同含義的域定義reaml
- scope:受權範圍,可選的,大小寫敏感的,空格分隔的列表(%x21 / %x23-5B / %x5D-7E),能夠是受權服務器定義的任何值,不該展現給終端用戶。OAuth 2.0還規定客戶端發送scope請求參數以指定受權訪問範圍,而在實際受權範圍與客戶端請求受權範圍不一致時,受權服務器可發送scope響應參數以告知客戶端下發的token實際的受權範圍。下爲兩個scope用法實例:
scope="urn:example:channel=HBO&urn:example:rating=G,PG-13"```
- error:描述訪問請求被拒絕的緣由,字符%x20-21 / %x23-5B / %x5D-7E以內
- error_description:向開發者提供一個可讀的解釋,字符%x20-21 / %x23-5B / %x5D-7E以內
- error_uri:absolute URI,標識人工可讀解釋錯誤的頁面,字符%x21 / %x23-5B / %x5D-7E以內.當錯誤發生時,資源服務器將發送的HTTP Status Code(一般是400, 401, 403, 或405)及Error Code以下:
- invalid_request:請求丟失參數,或包含無效參數、值,參數重複,多種方法發送access token,畸形等。資源服務器將發送HTTP 400 (Bad Request)
- invalid_token:access token過時、廢除、畸形,或存在其餘無效理由的狀況。資源服務器將發送HTTP 401 (Unauthorized),而客戶端則須要申請一個新的access token,而後才能從新發送該資源請求
bearer token response:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"mF_9.B5f-4.1JqM",
"token_type":"Bearer",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA"
}
```
-
安全威脅:
- token 僞造/修改: 攻擊者僞造/修改 已有的 token,致使資源服務器受權 經過非法訪問的客戶端,所以須要對 token 使用數字簽名或者消息認證碼來保證完整性。
- token 泄漏:自己包含認證、有效期等敏感信息,因此須要加密。
- token 改寄:攻擊者用一個訪問A資源服務器的token去請求B資源服務器的資源。所以一般 token 中能夠包含表明資源服務器的標識 來防止這種狀況的發生。
- token 重放:攻擊者企圖使用曾經使用過的token來請求資源。所以token需包含有效期(好比少於1小時)
5. 參考: