添加CallOptions传Bearer Token时GRPC客户端调用报错:方法不支持
解决ProtoBuf.Grpc代码优先模式下传递Bearer Token的问题
问题原因
你在服务方法中添加CallOptions参数的写法不符合ProtoBuf.Grpc代码优先的约定:
CallOptions是gRPC用于传递调用元数据、超时等控制信息的载体,不属于业务请求消息的一部分- 框架会将方法中的额外参数识别为gRPC请求的字段,但
CallOptions无法被序列化为protobuf消息,因此抛出NotSupportedException
正确实现方式
1. 修正服务端代码
移除服务方法中的CallOptions参数,保持接口定义的纯净性。如果需要获取Token,可通过HttpContext或CallContext获取:
[Authorize] public class CustomerService : ICustomerService { private readonly IMediator _mediator; private readonly IHttpContextAccessor _httpContextAccessor; public CustomerService(IMediator mediator, IHttpContextAccessor httpContextAccessor) { _mediator = mediator; _httpContextAccessor = httpContextAccessor; } public Task CreateCustomer(CreateCustomerCommand request) { // 如需手动获取Token(跳过[Authorize]时使用) var authHeader = _httpContextAccessor.HttpContext.Request.Headers["Authorization"].ToString(); if (!string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("Bearer ")) { var token = authHeader.Substring(7); // 这里可以处理token逻辑 } return _mediator.Send(request); } }
2. 客户端正确传递Token
在调用gRPC方法时,通过CallOptions添加Authorization元数据,无需修改服务方法定义:
// 构造包含Bearer Token的CallOptions var token = "your-jwt-token-here"; var callOptions = new CallOptions { Headers = new Metadata { { "Authorization", $"Bearer {token}" } } }; // 调用服务方法时传入callOptions await customerService.CreateCustomer(request, callOptions);
3. 推荐:使用ASP.NET Core内置认证授权
在ASP.NET Core gRPC服务中,推荐配合JWT认证中间件实现Token验证,无需手动处理:
配置认证中间件(Program.cs)
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) }; // 适配gRPC的Header解析 options.Events = new JwtBearerEvents { OnMessageReceived = context => { var authHeader = context.Request.Headers["Authorization"].FirstOrDefault(); if (!string.IsNullOrEmpty(authHeader)) { context.Token = authHeader.Split(" ").Last(); } return Task.CompletedTask; } }; }); builder.Services.AddAuthorization(); builder.Services.AddHttpContextAccessor(); // 启用认证和授权 app.UseAuthentication(); app.UseAuthorization();
这样只要服务类或方法加上[Authorize]特性,框架会自动验证Token的有效性,无需手动解析。
内容的提问来源于stack exchange,提问作者Ali Zafar
相关产品推荐
相关产品推荐

