open sesame(芝麻開門) - Ali Baba and the Forty Thievesweb
咱們在開發api接口時,有時候須要對某些接口進行受權,容許有權限的用戶才能訪問。對用戶進行權限管理一般能夠經過cookie/session,token等機制來實現。這些方式比較適合相對複雜的業務權限處理,而http自己提供了一種相對簡單的受權方式,就是http basic auth。上節中,咱們提到的metrics相關的接口,是須要進行受權後,才能訪問,而監控接口主要被內部的監控系統所使用,自己和具體的業務無關,使用http basic auth機制比較切合。算法
Basic Auth是http協議提供的一個簡單的認證機制,當咱們訪問某個受保護的資源(url)時,http服務器將告知客戶端該資源須要受權才能訪問,隨後客戶端提供相應的憑證(用戶名/密碼),服務端收到憑證進行校驗,確認無誤後,客戶端既可訪問受保護的資源,不然,將無權訪問。json
注意:後端
- 如用戶輸入的憑證信息不匹配,將會再次執行第二步操做,返回401響應(未受權)
- 不一樣的http客戶端,對basic auth的支持會有差別。典型的是經過瀏覽器訪問受保護的資源時,會彈出用戶名和密碼輸入框,而非瀏覽器客戶端,好比在APP中,經過http接口調用時,是不會彈出輸入框的。
下面咱們具體的看一下http協議的交互流程。api
客戶端發起GET請求瀏覽器
GET /actuator/metrics HTTP/1.1
...
複製代碼
服務器發現該資源須要受權訪問,而客戶端並未提供憑證信息,則向客戶端返回401響應(HTTP 401 Unauthorized),以及WWW-Authenticate頭部字段。安全
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Authorization Required"
Date: Sun, 24 Mar 2019 01:09:45 GMT
Content-Length: 0
複製代碼
WWW-Authenticate頭部字段:服務器
WWW-Authenticate: Basic realm="Authorization Required"
複製代碼
其中,Basic表示使用basic認證算法,realm表示區域,不一樣的區域可使用不一樣的用戶名和密碼。cookie
服務器也能夠帶上編碼字段,代表服務器指望客戶端使用相應的編碼去encode用戶名和密碼。session
WWW-Authenticate: Basic realm="Authorization Required", charset="UTF-8"
複製代碼
客戶端獲取到用戶名和密碼後,進行Base64編碼後,向服務器再次發起請求,請求中一般在header中經過Authorization字段帶上認證信息。
GET /actuator/metrics HTTP/1.1
Host: localhost:9800
Authorization: Basic YWRtaW46cGFzcw==
...
複製代碼
Authorization字段信息包含兩部分,第一部分是Basic,後面帶上一個空格;第二部分是用戶憑證信息的編碼。編碼過程以下:
好比:用戶名爲admin,密碼爲pass,則編碼時先進行組裝獲得字符串admin:pass,而後對字符串使用ASCII編碼,進行Base64後獲得字符串YWRtaW46cGFzcw==
服務器收到請求後,提取出Authorization字段,校驗匹配後,則返回200成功響應。
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Sun, 24 Mar 2019 01:11:00 GMT
Content-Length: 55
{"name":["all","mem.sys","mem.heap_objects","gc.last"]} 複製代碼
/health接口在客戶端請求時,若是沒有帶上basic auth信息,則返回簡單的服務健康信息。
GET /actuator/health HTTP/1.1
...
複製代碼
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 30
...
{"status":"up","statusCode":1}
複製代碼
若是客戶端請求時,帶上了認證信息,則返回詳細的服務健康信息。
GET /actuator/health HTTP/1.1
Authorization: Basic YWRtaW46cGFzcw==
...
複製代碼
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Sun, 24 Mar 2019 02:37:13 GMT
Content-Length: 224
{"details":{"disk":{"status":"up","details":{"free":912524103680,"threshold":0,"total":1127625711616}},"mem":{"status":"up","details":{"free":10098888704,"total":1 7035321344,"used":6936432640}}},"status":"up","statusCode":1} 複製代碼
這裏的實現和基本的basic auth流程將不同,它不會響應401。而是根據客戶端請求的狀況進行處理。
func ActuatorGetHealthInfo(c *gin.Context) {
showDetail := false
// 判斷是否使用basic auth
authHead := c.GetHeader("Authorization")
if strings.HasPrefix(authHead, "Basic ") {
// 獲取token
token := authHead[6:]
// 驗證token
shouldToken := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", utils.GetAppConfig().Management.Security.Account, utils.GetAppConfig().Management.Security.Password)))
if token == shouldToken {
// 憑證信息一致,將顯示詳細信息
showDetail = true
}
}
// 調用業務邏輯
r, _ := healthService.HealthInfo(showDetail)
// 組裝返回數據
c.JSON(http.StatusOK, r)
}
複製代碼
Basic Auth比較適合簡單的認證場景,尤爲是在內網中使用。一般咱們會配合https進行信息加密,來提升安全性。
本節經過實際的接口實例介紹了http basic auth的基本流程,優缺點以及應用場景。下一節,咱們將介紹關於Restful接口的相關信息、如何設計Restful風格的接口及實際開發過程當中比較好的工程實踐。
本文爲做者原創做品,屬於《從新學習web後端開發》專輯中的一篇,轉載時請備註做者信息及來源。本文原文地址:www.donnyzhang.com/2019/03/23/…