我目前正在开发一个Web应用程序,并在Go中使用中间件实现一个用户身份验证系统.我想知道在中间件中注入存储库或服务以进行用户身份验证的最佳方式是什么.

我想这样做的原因是,我想对每个用户身份验证使用存储库的方法.然而,我不确定在中间件中注入存储库或服务是否干净.

对于如何以一种干净和可维护的方式完成这项工作,有人有什么建议或最佳实践吗?

我已经阅读了关于Stackoverflow的this个问题,但它似乎与C#有关,并不一定是设计问题.

提前感谢您的见解.

推荐答案

也许有一百多种方法来回答你的问题,但我会试着根据我的经验来回答. 首先,如果我理解你的问题,你需要知道how to inject a repository on a middleware,然后才能知道它是不是a good practice.

关于你的first point分:

type AuthenticationRepository interface {
    GetApiKey(location string) (string, error)
}

func AuthorizationMiddleware(authRepo AuthenticationRepository) gin.HandlerFunc {
    return func(c *gin.Context) {
        // Get the location and key from headers
        location := c.GetHeader("Host")
        apiKey := c.GetHeader("Key")

        // Use the repository to get the API key from location
        expectedKey, err := authRepo.GetApiKey(location)
        if err != nil {
            log.Errorf("Unexpected error when trying to get api key: %v", err)
            c.AbortWithStatus(http.StatusServiceUnavailable)
            return
        }

        if expectedKey != apiKey {
            c.AbortWithStatus(http.StatusUnauthorized)
            return
        }

        // Call the next handler
        c.Next()
    }
}

通过这个基本示例,您可以在存储库上执行所需的操作.

关于你的second point美元,这是一个很好的练习吗?如果你只有很少的用户或服务,yes,你不会有问题. 但是,如果您想拥有一个拥有大量用户的可扩展基础设施:no, this is not a good practice.

Why?,因为您的所有服务都必须从存储库中检索信息.因此,您在所有终端上引入了SPOF和大量延迟. 您可以进行一些缓存,但如果您有大量用户,则很难进行管理.

要处理这个问题,您需要知道authenticationauthorization之间的区别:authentication验证用户或服务的身份,而authorization确定他们的访问权限.

例如,您可以使用HIS username/password(或使用HIS client_id/client_secret的服务)为用户设置authenticate,然后,在身份验证之后,您的授权服务将提供JWT token.该令牌被签名,并且可以由具有对应public key的任何服务来验证.因此,您不需要针对每个请求从存储库访问特定的服务/存储,因为使用此public key,您可以授权访问请求(取决于其他经过验证的令牌声明).

有关JWT和Flow的一些文档可以获得它:

因此,所有这些都取决于用户数量:)

Go相关问答推荐

出口上下文值密钥的安全方法?

try 用GitHub操作中的release标签更新version. go文件,但失败了

为什么Slices包中的函数定义Slice参数的类型参数?

Go:拆分一个由逗号分隔的键/值对字符串,并在给定的键/价值对中嵌入可能的逗号

Go 1.20 中如何计算连接错误?

在VSCode中如何使用特定的文件名提供编译命令

如何将任何类型的数据值传递到 Golang 中的 GRPC Protobuf struct ?

正确的 shell 程序进入 golang alpine docker 容器的入口点?

如何在 fyne-io/fyne 中设置文本的字母间距?

Go 中的 Azure JWT 验证不起作用

GitHub 中 REST API 的 aws 凭证问题

如何使用 go-git 将特定分支推送到远程

golang yaml 马歇尔网址

闭包所处的环境范围是什么?

没有任务角色的 AWS CDK ECS 任务定义

Go http.FileServer 给出意外的 404 错误

使用反射在 struct 内迭代切片 struct

使用 xml.Name 将 xml 解组为 [] struct

退格字符在围棋操场中不起作用

如何扩充 ResponseWriter 的 Header() 返回的 map