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/…