我正在使用微服务开发应用程序,而且我不知道如何分发微服务以允许使用身份验证。
我已经读过每个微服务应该有自己的数据库以避免耦合。
问题是身份验证(通过JWT)和用户微服务必须能够访问相同的数据库和表(用户)。我想这个问题之前已经解决,因为类似的应用程序必须处理同样的问题。
我该如何解决这个问题?
答案 0 :(得分:14)
JWS(JWT的签名版本)是一个完美的例子,因为它被认为是类似的scnearios:
signin.domain.com
),一旦您验证用户的凭据,就会发出通过私钥生成的令牌强> service1.domain.com
,service2.domain.com
)都可以实施一个中间件,而不是授权:您的所有服务都会收到公钥和将能够通过该密钥验证令牌的真实性。他们不需要数据库,因为他们需要验证的是令牌是有效的,而不是用户存在等等。澄清我的上一个陈述:你应该发行非常短命的代币。那时,说:
service.domain.com
在service.domain.com
上,您仍然会认为他已登录,直到您需要与实际访问数据库的API进行交互(即添加新的用户地址)。此时,负责写入数据库的服务将抛出异常,表示用户不存在,您可以捕获它并将用户注销。所有这一切都可以进行调整/微调,但你会大致了解它是如何工作的。
回到JWT及其用法,我不知道您是否熟悉PHP,但这是pretty straightforward example。
如果你想获得幻想,你可以使用nginx作为中间件,并为你做auth module授权。
最后但并非最不重要的是,我们这里只介绍了身份验证:要进行授权,您可能要么在每个服务中要么从令牌中读取用户的角色(假设您在用户登录后将其保存在那里 - - 但这有点瑕疵,好像用户失去了一个角色,然后他的令牌仍会列出它)或者只是从每个服务调用signin.domain.com/users/me
来检索最新的用户角色列表,然后检查一下他被允许对该特定服务执行某些操作。
哦,请记住,您不应该将敏感数据放在JWT / JWS中,因为它们可以被解码。所以,是的,您可以将用户角色添加到JWT,但是,例如,永远不要在那里保存密码或其他明文标记。
希望这有帮助!
答案 1 :(得分:1)
我们通过使用服务组合来保护需要身份验证的服务来解决这个问题。如果它是一块巨石,很像你接近它的方式。
正如@odino所说:
以下是StdLib(我们在内部使用的内容)的示例:
const lib = require('lib');
module.exports = function(params, callback) {
lib.user.isAuthenticated(params, (err, user) => {
if (err) return callback(err);
// We're authenticated – do the rest of the work.
});
}
需要注意的是,如果您使用HTTP作为协议在您的服务之间进行通信,那么您实际上是在为身份验证添加了200-300毫秒的开销。您可以通过在同一个容器中加载需要身份验证的服务来解决这个问题(StdLib开箱即用)。
答案 2 :(得分:0)
我们使用的策略略有不同。我们已经跳过JWT的签名或加密,这使得我们的JWT只是我们的令牌对象的Base64编码字符串,一旦创建的JWT对我们所有的微服务都有效。我们确保我们的微服务无法直接访问,只能通过Api网关访问。 API网关执行身份验证(Http Basic),生成令牌,缓存令牌并为每个请求验证它,然后在委托给微服务时将其作为标头传递。这个微服务只需传递从Api Gateway收到的JWT即可访问另一个服务,我们使用JWT作为一种机制来了解登录用户是谁。
接收到请求后的每个微服务都会检查标头中是否存在JWT。如果存在,则获取可用于令牌中指定的用户的权限,并将其用于授权。授权(特权)确保合适的人试图访问资源。