пытается выполнить аутентификацию Azure AD с помощью gRPC-Web с помощью protobuf-net

Я пытаюсь выполнить аутентификацию Azure AD с помощью gRPC-Web в приложении веб-сборки Blazor. Я использую 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?

1 ответ

Решение

Похоже, проблема в том, что вы используете ServerCallContextв сигнатуре метода; базовое ядро ​​gRPC имеет отдельные API контекста клиент / сервер, но это не подходит для использования в независимом интерфейсе, и поэтому protobuf-net.Grpc объединяет эти два API через 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)

В CallContext API предоставляет общие серверные и клиентские API (заголовки, отмена и т. Д.) Одним способом, или вы можете использовать (например) context.ServerCallContextчтобы получить специфичный для сервера API, если это необходимо (это вызовет исключение, если используется в контексте клиента). Для использования на стороне клиента CallContext можно построить из CallOptions, который является основным клиентским API gRPC, например:

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

Я открыт для идеи разрешить CallContext создаваться непосредственно из Metadata / CancellationToken и т. д. (позволяя var result = await service.CreateCustomer(customer, headers);) - но это не кажется существенным.

Другие вопросы по тегам