1

我正在尝试在 blazor webassembly 应用程序中使用 gRPC-Web 进行 Azure AD 身份验证。我正在使用 protobuf-net 来帮助我进行序列化。我不确定如何传递令牌以让服务器端识别它。这就是我所拥有的:

var headers = new Metadata
               {
                 { "Authorization", $"Bearer {Token}" }
               };

并且,我将其作为参数发送到我想要使用的方法中

var result = await Client.CreateCustomer(this.customer, headers);

这是注入服务的方式:

builder.Services.AddTransient(services =>
        {
            var httpClient = new HttpClient(new GrpcWebHandler(GrpcWebMode.GrpcWeb, new HttpClientHandler()));
            var channel = Grpc.Net.Client.GrpcChannel.ForAddress("****", new GrpcChannelOptions { HttpClient = httpClient });
            return channel.CreateGrpcService<Application.Services.ICustomerService<ServerCallContext>>();
        });

这是服务的发布方式:

endpoints.MapGrpcService<CustomerService>().RequireAuthorization().EnableGrpcWeb()

而且,这是实现:

public class CustomerService : ICustomerService<ServerCallContext>
{
    [Authorize]
    public async ValueTask<Customer> CreateCustomer(Customer customerDTO, ServerCallContext context) 
    {****}
}

我得到的错误是无法从“Grpc.Core.Metadata”转换为“Grpc.Core.ServerCallContext”,这很明显。

我发现的参考使用了元数据,但我应该使用的是 ServerCallContext https://docs.microsoft.com/en-us/dotnet/architecture/grpc-for-wcf-developers/metadata 所以我错过了什么,我做错了什么,如何使用 protobuf-net 正确使用两者?

4

1 回答 1

2

看起来这里的问题是您ServerCallContext在方法签名中使用;底层 gRPC 核心具有单独的客户端/服务器上下文 API,但这不适合在不可知的接口上使用,因此,protobuf- net.Grpc通过CallContext. 所以:而不是:

async ValueTask<Customer> CreateCustomer(Customer customerDTO, ServerCallContext context)

对于签名,请考虑:

async ValueTask<Customer> CreateCustomer(Customer customerDTO, CallContext context)

或者

async ValueTask<Customer> CreateCustomer(Customer customerDTO, CallContext context = default)

API 以单一方式公开常见的CallContext服务器端和客户端 API(标头、取消等),或者您可以(例如)在需要时使用(例如)context.ServerCallContext获取特定于服务器的 API(如果使用这将引发异常在客户端上下文中)。对于客户端使用,CallContext可以从 a 构造 a CallOptions,这是核心 gRPC 客户端 API,例如:

var result = await service.CreateCustomer(customer, new CallOptions(headers));

我对允许直接从/ etc (允许)创建的想法持开放态度- 但它似乎并不重要CallContextMetadataCancellationTokenvar result = await service.CreateCustomer(customer, headers);

于 2020-10-26T14:12:41.277 回答