我目前正在开发一个Web应用程序,并在Go中使用中间件实现一个用户身份验证系统.我想知道在中间件中注入存储库或服务以进行用户身份验证的最佳方式是什么.
我想这样做的原因是,我想对每个用户身份验证使用存储库的方法.然而,我不确定在中间件中注入存储库或服务是否干净.
对于如何以一种干净和可维护的方式完成这项工作,有人有什么建议或最佳实践吗?
我已经阅读了关于Stackoverflow的this个问题,但它似乎与C#有关,并不一定是设计问题.
提前感谢您的见解.
我目前正在开发一个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和大量延迟. 您可以进行一些缓存,但如果您有大量用户,则很难进行管理.
要处理这个问题,您需要知道authentication和authorization之间的区别:authentication验证用户或服务的身份,而authorization确定他们的访问权限.
例如,您可以使用HIS username/password(或使用HIS client_id/client_secret的服务)为用户设置authenticate,然后,在身份验证之后,您的授权服务将提供JWT token.该令牌被签名,并且可以由具有对应public key的任何服务来验证.因此,您不需要针对每个请求从存储库访问特定的服务/存储,因为使用此public key,您可以授权访问请求(取决于其他经过验证的令牌声明).
有关JWT和Flow的一些文档可以获得它:
因此,所有这些都取决于用户数量:)