BasicAuth认证(gin框架提供)与Go

BasicAuth认证与Go

Basic Auth是一种开放平台认证方式,简单的说就是需要你输入用户名和密码才能继续访问。Bath Auth是其中一种认证方式,另一种是OAuth。

Basic Auth认证处理简单几乎没有什么优点了,最大的缺点就是安全性低。不用说,OAuth认证方式克服了Basic Auth认证的所有缺点,并且也是目前广泛应用的。

gin框架提供了Bath Auth认证中间件,我们来看看该怎么玩。

首先是服务端代码:

package main

import "gopkg.in/gin-gonic/gin.v1"

var secrets = gin.H{
    "foo":    gin.H{"email": "foo@bar.com", "phone": "123433"},
    "austin": gin.H{"email": "austin@example.com", "phone": "666"},
    "lena":   gin.H{"email": "lena@guapa.com", "phone": "523433"},
}

func getSecrets(c *gin.Context) {
    user := c.MustGet(gin.AuthUserKey).(string)
    if secret, ok := secrets[user]; ok {
        c.JSON(200, gin.H{"user": user, "secret": secret})
    } else {
        c.JSON(200, gin.H{"user": user, "secret": "No SECRET :("})
    }
}

func main() {
    r := gin.Default()
    authorized := r.Group("/admin", gin.BasicAuth(gin.Accounts{
        "foo":    "bar", //用户名:密码
        "austin": "1234",
        "lena":   "hello2",
        "manu":   "4321",
    }))
    authorized.GET("/secrets", getSecrets)
    r.Run(":8080")
}

让我们从main函数开始。Group函数注册了一个群组路由,gin.BasicAuth就是中间件,它的参数gin.Accounts其实是一个map[string]string类型的映射,这里是用来记录用户名和密码。

然后在路由/admin之下,又注册了/secrets路由,所以他的完整路由应该是/admin/secrets。处理器是getSecrets函数。

getSecrets函数中,首先从上下文gin.Context中获取用户名。gin.AuthUserKey是一个字符串常量,定义如下:

const AuthUserKey = "user"

这里获取的用户名就是你访问这个URL时输入的用户名,后台会验证密码,如果用户名和密码都对上了,认证才会成功。

接下来会利用获得的用户名去secrets结构中查找用户信息。gin.H是一个map[string]interface{}的映射。最后通过JSON返回查询结果。

现在万事具备,让我们用在浏览器中输入localhost:8080/admin/secrets进行访问,不出意外你会看到一个提示框,要你输入用户名和密码。用户名输入foo,密码输入bar。然后你就能看到一个关于foo的信息的JSON串了。

下面让我们用curl试试。打开PowerShell,输入curl localhost:8080/admin/secrets,然后帅气的回车。

。。。

为什么什么也没有?

再次输入curl -I localhost:8080/admin/secrets回车,查看响应头,得到的居然是一个401的响应。这是很正常的,应为你并没有提供任何有关用户名和密码的信息,所以认证必然是失败的,认证失败就会得到401的响应。

我们可以看看BasicAuth函数的源代码:

func BasicAuth(accounts Accounts) HandlerFunc {
    return BasicAuthForRealm(accounts, "")
}

继续追查BasicAuthForRealm函数:

func BasicAuthForRealm(accounts Accounts, realm string) HandlerFunc {
    pairs := processAccounts(accounts)

    return func(c *Context) {
        user, found := pairs.searchCredential(c.Request.Header.Get("Authorization"))
        if !found {
            c.AbortWithStatus(401)
        } else {
            c.Set(AuthUserKey, user)
        }
    }
}

让我们省略一些无关紧要的细节。这里的accounts就是我们调用BasicAuth函数时带入的用户名-密码映射,这里需要用来进行身份验证。最后返回了一个匿名函数,这个匿名函数就是中间件。

在匿名函数中首先会去请求头中去查找Authorization请求首部,如果找到了,就调用Set函数把这个请求首部中的用户名设置到上下文,也就是gin.Context中。无独有偶,这里我们又看到了AuthUserKey,现在你知道为什么在getSecrets函数中我们要用它去获取用户名了吧。需要注意的是searchCredential函数除了获取用户名还会进行密码验证。

如果请求头中没有Authorization请求首部,那么恭喜,你将毫无悬念的得到401响应。

所以,当我们使用curl访问时,需要设置一下请求头。但是问题又来了,该如何设置请求头呢?

不要紧,其实想通过验证只需要在访问时提供用户名和密码就行了,这一要求通过URL也是可以办到的。如下:

curl foo:bar@localhost:8080/admin/secrets

这次就能看到返回的JSON串了。是这样子的:

{"secret":{"email":"foo@bar.com","phone":"123433"},"user":"foo"}

既然这样,我们不妨再看看这样访问时curl发送给服务器的请求头是怎样的。通过-v选项能达到这一目的:

curl -v foo:bar@localhost:8080/admin/secrets

这是我们将得到如下的输出:

> GET /admin/secrets HTTP/1.1
> Host: localhost:8080
> Authorization: Basic Zm9vOmJhcg==
> User-Agent: curl/7.60.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Date: Wed, 11 Jul 2018 06:14:26 GMT
< Content-Length: 64
<
{"secret":{"email":"foo@bar.com","phone":"123433"},"user":"foo"}

>符号后面的是请求,<符号后面的是响应。我们注意到请求头中有这样一行请求首部:

Authorization: Basic Zm9vOmJhcg==

这正是我们苦苦寻觅的验证信息!不过Basic后面一串乱码又是什么鬼?

其实那不是乱码,那是foo:bar经过base64编码后的结果。也就是说,写在请求头中的验证信息必须经过base64编码。这里提供一个网站可以在线进行base64编解码。有关认证的更多信息可以访问这里

如果想通过设置请求头进行验证,按照上面的模式设置请求头就可以啦。下面让我们用这种方式来获取austin的秘密。首先需要访问base64编码网站,得到austin:1234经过编码后的内容,然后在PowerShell中输入以下命令:

curl -v -H 'Authorization: Basic YXVzdGluOjEyMzQ=' localhost:8080/admin/secrets

-H用来向请求头添加自定义字段。再次帅气的回车,你将得到以下内容:

> GET /admin/secrets HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.60.0
> Accept: */*
> Authorization: Basic YXVzdGluOjEyMzQ=
>
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Date: Wed, 11 Jul 2018 08:35:21 GMT
< Content-Length: 71
<
{"secret":{"email":"austin@example.com","phone":"666"},"user":"austin"}

成功获取austin的秘密,是不是666。

最后总结一下认证的三种方式:

  1. 通过浏览器访问,输入用户名和密码;
  2. 通过URL提供用户名和密码,如:user:password@localhost:8080/admin/secrets;
  3. 通过在请求头中添加Authorization字段提供用户名和密码,需要经过base64编码。
  • 12
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值