我有一套微服务,其中一个负责身份验证。所有服务都使用共享库,例如flask_jwt_extended,以及用于验证传入请求的共享密钥(例如,使用flask_jwt_extended的jwt_required
装饰器)。
身份验证服务的主要端点是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
装饰器保护端点,这些装饰器仅验证传入请求的令牌(没什么特别的):
class PostDetails(Resource):
@jwt_required
def get(self, post_id):
pass
当然,所有服务都共享相同的密钥:
app = app = Flask(__name__,)
app.config.from_mapping(JWT_SECRET_KEY=os.environ['JWT_SECRET_KEY'])
注销操作理想地应如下:
我的问题是:
如何在不引入服务之间进一步耦合的情况下检查其他服务(auth服务除外)中被阻止的令牌?
是否可以通过不共享任何库或密钥进一步分离服务?
编辑:我为问题添加了更多详细信息和代码段,希望可以更好地阐明和说明问题。
答案 0 :(得分:1)
基于以上评论。
简短的回答是,是的,这可能会增加auth服务的开销,但这是分离服务并将身份验证逻辑限制在同一服务中的最佳方法。
另一种方法是将令牌放入分布式缓存中,并在令牌被列入黑名单时对其进行验证。您只能将令牌保留在令牌的有效期限内的缓存中。假设您的令牌到期时间为15分钟,那么您将仅检查最近15分钟内生成的缓存中的令牌,其余令牌无论如何都已过期,可以删除。这样可以使缓存的大小保持较小,并且可以更快地进行检查。可以在所有服务之间共享此缓存服务。
通常,我们具有验证令牌的网关服务(公共端点),并且该服务可以调用缓存服务以检查令牌是否在缓存黑名单中。