You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 07:00:58