Authentication 如何在微服务体系结构中将身份验证服务与其他服务分离?

Authentication 如何在微服务体系结构中将身份验证服务与其他服务分离?,authentication,flask,microservices,logout,coupling,Authentication,Flask,Microservices,Logout,Coupling,我有一套微服务,其中一个负责认证。所有服务都使用共享库(例如)和共享密钥来验证传入请求(例如,使用jwt_requireddecorator) 身份验证服务的主要端点是UserLogin和UserLogout,类似于: class UserLogin(Resource): def __init__(self, *args, **kwargs): self.parser = reqparse.RequestParser() self.parser.add_

我有一套微服务,其中一个负责认证。所有服务都使用共享库(例如)和共享密钥来验证传入请求(例如,使用
jwt_required
decorator)

身份验证服务的主要端点是UserLogin和UserLogout,类似于:

class UserLogin(Resource):

    def __init__(self, *args, **kwargs):
        self.parser = reqparse.RequestParser()
        self.parser.add_argument('email', type=str, required=True)
        self.parser.add_argument('password', type=str, required=True)


    def post(self):
        args = self.parser.parse_args()
        email = args.get('email')
        password = args.get('password')

        user = User.query.filter_by(email=email).first()
        if not user:
            return jsonify({'message': 'User does not exist'})

        if user.verify_hash(password):
            access_token = create_access_token(identity=user.email) 
            return jsonify({'access_token': access_token})
        else:
            return jsonify({'message': 'Wrong credentials'})


class UserLogout(Resource):

    @jwt_required
    def post(self):
        #Get the token and presist 
        jti = get_raw_jwt()['jti']        
        blocked_token = BlockedTokens(jti=jti) 
        db.session.add(blocked_token)
        db.session.commit()
        return jsonify({'message': 'logged out'})
然后,在其他服务中,我使用
jwt_required
decorators保护端点,它只验证传入请求的令牌(没有什么特别的):

当然,所有服务共享相同的密钥:

app = app = Flask(__name__,)
app.config.from_mapping(JWT_SECRET_KEY=os.environ['JWT_SECRET_KEY']) 
理想情况下,注销操作应如下所示:

  • 将访问令牌存储在身份验证服务的数据库中
  • 对于每个请求,如果其令牌在黑名单中,则阻止它
  • 我的问题是:

  • 如何在其他服务(除了身份验证服务)中检查被阻止的令牌,而不引入服务之间的进一步耦合

  • 是否可以通过不共享任何库或密钥来进一步解耦服务


  • 编辑:我在问题中添加了更多的细节和代码片段,我希望它能得到更好的澄清和证明

    基于上述评论

    简短的回答是肯定的,这可能会增加身份验证服务的开销,但这是将服务解耦并将身份验证逻辑限制在同一服务中的最佳方法

    另一种方法是将令牌放在分布式缓存中,并验证令牌是否被列入黑名单。您只能将令牌保留在令牌到期时间段内的缓存中。假设您的令牌到期时间为15分钟,您将只检查缓存中在过去15分钟内生成的令牌,其余令牌仍然过期,可以删除。这将使缓存的大小保持较小,并且检查速度更快。此缓存服务可以在您的所有服务中共享


    通常,我们有网关服务(公共端点)来验证令牌,该服务可以调用缓存服务来检查令牌是否在缓存黑名单中

    基于上述评论

    简短的回答是肯定的,这可能会增加身份验证服务的开销,但这是将服务解耦并将身份验证逻辑限制在同一服务中的最佳方法

    另一种方法是将令牌放在分布式缓存中,并验证令牌是否被列入黑名单。您只能将令牌保留在令牌到期时间段内的缓存中。假设您的令牌到期时间为15分钟,您将只检查缓存中在过去15分钟内生成的令牌,其余令牌仍然过期,可以删除。这将使缓存的大小保持较小,并且检查速度更快。此缓存服务可以在您的所有服务中共享


    通常,我们有网关服务(公共端点)来验证令牌,该服务可以调用缓存服务来检查令牌是否在缓存黑名单中

    注销操作的目的是什么?为什么仅仅从用户的浏览器中删除适当的令牌是不够的?是否存在您试图缓解的特定威胁?从浏览器中删除令牌并不意味着无法使用令牌。令牌将一直可用,直到过期。您是对的,这就是您将令牌列入黑名单的方式。通常我们选择短期访问令牌,比如15分钟到期时间,一旦令牌到期,您将通过刷新令牌发布新令牌。您始终可以撤销刷新令牌。通常,您将使用单个服务来验证令牌,因此每个服务和任何服务都将调用该服务来检查令牌的有效性。在您的情况下,任何其他服务将调用您的authentication svc来检查令牌的有效性。我认为从其他服务向身份验证服务发送请求以验证每个传入请求的令牌可能会带来网络开销和瓶颈(auth service),我说的对吗@ImranArshad?注销操作的目的是什么?为什么仅仅从用户的浏览器中删除适当的令牌是不够的?是否存在您试图缓解的特定威胁?从浏览器中删除令牌并不意味着无法使用令牌。令牌将一直可用,直到过期。您是对的,这就是您将令牌列入黑名单的方式。通常我们选择短期访问令牌,比如15分钟到期时间,一旦令牌到期,您将通过刷新令牌发布新令牌。您始终可以撤销刷新令牌。通常,您将使用单个服务来验证令牌,因此每个服务和任何服务都将调用该服务来检查令牌的有效性。在您的情况下,任何其他服务将调用您的authentication svc来检查令牌的有效性。我认为从其他服务向身份验证服务发送请求以验证每个传入请求的令牌可能会带来网络开销和瓶颈(auth service),我说的对吗@ImranArshad?所以在性能和解耦之间有一个折衷,谢谢。但是,如果像Kong do那样将身份验证逻辑移动到Api网关中,通过这样做,请求如何在体系结构中流动呢?通常,我们在Api网关中有身份验证逻辑。这样,并不是每个svc都必须验证令牌,因为所有其他微服务都必须是私有的,没有公共端点,而获取它们的唯一方法是通过api网关。因此,任何web请求都首先通过apigate方式。一旦所有内容都得到验证,我们会将其重定向到相应的微服务器。谢谢,现在事情更清楚了。很抱歉再次打扰您,但是如果我决定在api网关下使用身份验证服务,在api网关将所有请求定向到正确的服务之前,所有请求都会被定向到此身份验证服务
    app = app = Flask(__name__,)
    app.config.from_mapping(JWT_SECRET_KEY=os.environ['JWT_SECRET_KEY'])