Akka gRPC授权拒绝返回13 INTERNAL错误,如何改为UNAUTHENTICATED(16)?
问题描述
在Akka gRPC与Akka Http互集成的场景下,实现授权校验逻辑时,无论通过调用reject还是抛出自定义AuthenticationException,校验失败后始终返回gRPC的13 INTERNAL内部错误,而非预期的16 UNAUTHENTICATED认证错误,自定义Akka Http的ExceptionHandler也无法解决该问题。
代码示例:
- 方式1:使用reject
val authorizationDirective: Directive0 = headerValueByName("token").flatMap { token => if (token == "XYZ") pass else reject }
- 方式2:抛出自定义异常
val authorizationDirective: Directive0 = headerValueByName("token").flatMap { token => if (token == "XYZ") pass else throw new AuthenticationException("Invalid Token!") }
错误日志:
01:06:50.972|ERROR| akka.actor.ActorSystemImpl Error during processing of request: 'Invalid Token!'. Completing with 500 Internal Server Error response. To change default exception handling behavior, provide a custom ExceptionHandler. com.xworks.affixzone.api.integration.definition.exception.AuthenticationException: Invalid Token!
解决方案
Akka gRPC对错误的处理逻辑独立于普通Akka Http的异常/拒绝处理,需要使用其专属的错误映射机制才能返回正确的gRPC状态码:
方案1:直接抛出GrpcServiceException
使用Akka gRPC提供的GrpcServiceException,构造时传入Status.UNAUTHENTICATED状态,这是最直接的方式:
import akka.grpc.GrpcServiceException import io.grpc.Status val authorizationDirective: Directive0 = headerValueByName("token").flatMap { token => if (token == "XYZ") pass else throw new GrpcServiceException( Status.UNAUTHENTICATED.withDescription("Invalid or missing authorization token") ) }
方案2:自定义GrpcExceptionHandler映射异常
如果希望保留自定义的AuthenticationException,可以通过自定义GrpcExceptionHandler将其映射为UNAUTHENTICATED状态:
import akka.grpc.GrpcExceptionHandler import io.grpc.Status // 自定义异常处理器 val customGrpcExceptionHandler = GrpcExceptionHandler { case authEx: AuthenticationException => Status.UNAUTHENTICATED.withDescription(authEx.getMessage) // 保留其他异常的默认处理(可选) case otherEx => GrpcExceptionHandler.default(otherEx) } // 启动gRPC服务时配置该处理器 GrpcServer.start( handler = MyGrpcServiceHandler.withServerReflection(...), port = 8080, grpcExceptionHandler = customGrpcExceptionHandler, system = actorSystem )
为什么之前的方法无效?
Akka gRPC默认会将未被其专属处理器捕获的Rejection或普通异常统一映射为INTERNAL(13)错误,普通Akka Http的ExceptionHandler或RejectionHandler不会参与gRPC请求的错误转换流程,必须使用Akka gRPC提供的错误处理机制才能生成符合预期的gRPC状态码。
内容的提问来源于stack exchange,提问作者kkurt
相关产品推荐
相关产品推荐

