Sdílet prostřednictvím


Ověřování a autorizace v gRPC pro ASP.NET Core

Poznámka:

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Upozorňující

Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v tématu .NET a .NET Core Zásady podpory. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Důležité

Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.

Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Autor: James Newton-King

Zobrazení nebo stažení ukázkového kódu (postup stažení)

Ověřování uživatelů, kteří volají službu gRPC

GRPC lze použít s ověřováním ASP.NET Core k přidružení uživatele k jednotlivým voláním.

Následuje příklad Program.cs použití gRPC a ověřování ASP.NET Core:

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapGrpcService<GreeterService>();

Poznámka:

Pořadí, ve kterém zaregistrujete middleware ověřování ASP.NET Core, záleží. Vždy zavolat UseAuthentication a za a před UseRouting UseEndpoints.UseAuthorization

Ověřovací mechanismus, který vaše aplikace používá během volání, je potřeba nakonfigurovat. Konfigurace ověřování se přidá Program.cs a bude se lišit v závislosti na mechanismu ověřování, který vaše aplikace používá.

Po nastavení ověřování je uživatel přístupný v metodách služby gRPC prostřednictvím ServerCallContextmetody .

public override Task<BuyTicketsResponse> BuyTickets(
    BuyTicketsRequest request, ServerCallContext context)
{
    var user = context.GetHttpContext().User;

    // ... access data from ClaimsPrincipal ...
}

Ověřování nosný token

Klient může poskytnout přístupový token pro ověřování. Server token ověří a použije ho k identifikaci uživatele.

Na serveru se ověřování nosných tokenů konfiguruje pomocí middlewaru JWT Bearer.

V klientovi .NET gRPC lze token odeslat s voláními pomocí Metadata kolekce. Položky v kolekci Metadata se odesílají s voláním gRPC jako hlavičky HTTP:

public bool DoAuthenticatedCall(
    Ticketer.TicketerClient client, string token)
{
    var headers = new Metadata();
    headers.Add("Authorization", $"Bearer {token}");

    var request = new BuyTicketsRequest { Count = 1 };
    var response = await client.BuyTicketsAsync(request, headers);

    return response.Success;
}

Nastavení nosné tokeny pomocí CallCredentials

Konfigurace ChannelCredentials v kanálu představuje alternativní způsob odeslání tokenu do služby pomocí volání gRPC. A ChannelCredentials může zahrnovat CallCredentials, které poskytují způsob, jak automaticky nastavit Metadata.

Výhody použití CallCredentials:

  • Ověřování je centrálně nakonfigurované v kanálu. Token nemusí být ručně poskytnut volání gRPC.
  • CallCredentials.FromInterceptor Zpětné volání je asynchronní. V případě potřeby může volání přihlašovacích údajů načíst token přihlašovacích údajů z externího systému. Asynchronní metody uvnitř zpětného volání by měly používat on CancellationToken AuthInterceptorContext.

Poznámka:

CallCredentials jsou použity pouze v případě, že je kanál zabezpečený protokolem TLS. Odesílání hlaviček ověřování přes nezabezpečené připojení má vliv na zabezpečení a nemělo by se provádět v produkčních prostředích. Aplikace může nakonfigurovat kanál tak, aby toto chování ignoroval a vždy ho používal CallCredentials nastavením UnsafeUseInsecureChannelCallCredentials kanálu.

Přihlašovací údaje v následujícím příkladu konfigurují kanál tak, aby odesílal token s každým voláním gRPC:

private static GrpcChannel CreateAuthenticatedChannel(ITokenProvder tokenProvider)
{
    var credentials = CallCredentials.FromInterceptor(async (context, metadata) =>
    {
        var token = await tokenProvider.GetTokenAsync(context.CancellationToken);
        metadata.Add("Authorization", $"Bearer {token}");
    });

    var channel = GrpcChannel.ForAddress(address, new GrpcChannelOptions
    {
        Credentials = ChannelCredentials.Create(new SslCredentials(), credentials)
    });
    return channel;
}

Nosný token s klientskou továrnou gRPC

Klientská továrna gRPC může vytvářet klienty, kteří odesílají nosný token pomocí AddCallCredentials. Tato metoda je k dispozici v Grpc.Net.ClientFactory verze 2.46.0 nebo novější.

Delegát předaný je AddCallCredentials spuštěn pro každé volání gRPC:

builder.Services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
        o.Address = new Uri("https://localhost:5001");
    })
    .AddCallCredentials((context, metadata) =>
    {
        if (!string.IsNullOrEmpty(_token))
        {
            metadata.Add("Authorization", $"Bearer {_token}");
        }
        return Task.CompletedTask;
    });

Injektáž závislostí (DI) lze kombinovat s AddCallCredentials. Přetížení se předá IServiceProvider delegátu, který lze použít k získání služby vytvořené z DI pomocí vymezených a přechodných služeb.

Představte si aplikaci, která má:

  • Uživatelem definovaný ITokenProvider pro získání nosné tokeny. ITokenProvider aplikace is registered in DI with a scoped lifetime.
  • Klientská továrna gRPC je nakonfigurovaná tak, aby vytvářela klienty vložené do služeb gRPC a řadičů webového rozhraní API.
  • Volání gRPC by se měla použít ITokenProvider k získání nosný token.
public interface ITokenProvider
{
    Task<string> GetTokenAsync(CancellationToken cancellationToken);
}

public class AppTokenProvider : ITokenProvider
{
    private string _token;

    public async Task<string> GetTokenAsync(CancellationToken cancellationToken)
    {
        if (_token == null)
        {
            // App code to resolve the token here.
        }

        return _token;
    }
}
builder.Services.AddScoped<ITokenProvider, AppTokenProvider>();

builder.Services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
        o.Address = new Uri("https://localhost:5001");
    })
    .AddCallCredentials(async (context, metadata, serviceProvider) =>
    {
        var provider = serviceProvider.GetRequiredService<ITokenProvider>();
        var token = await provider.GetTokenAsync(context.CancellationToken);
        metadata.Add("Authorization", $"Bearer {token}");
    }));

Předchozí kód:

  • ITokenProvider Definuje a AppTokenProvider. Tyto typy zpracovávají překlad ověřovacího tokenu pro volání gRPC.
  • Zaregistruje AppTokenProvider typ v oboru životnosti pomocí DI. AppTokenProvider uloží token do mezipaměti, aby se k výpočtu vyžadovalo pouze první volání v oboru.
  • Zaregistruje typ v GreeterClient klientské továrně.
  • Konfiguruje AddCallCredentials pro tohoto klienta. Delegát se spustí při každém volání a přidá token vrácený ITokenProvider do metadat.

Ověřování klientských certifikátů

Klient může případně poskytnout klientský certifikát pro ověřování. Ověřování certifikátů probíhá na úrovni protokolu TLS, dlouho předtím, než se někdy dostane k ASP.NET Core. Když požadavek zadá ASP.NET Core, balíček ověřování klientských certifikátů umožňuje přeložit certifikát na ClaimsPrincipal.

Poznámka:

Nakonfigurujte server tak, aby přijímal klientské certifikáty. Informace o přijetí klientských certifikátů ve Kestrelslužbě , IIS a Azure najdete v tématu Konfigurace ověřování certifikátů v ASP.NET Core.

V klientovi .NET gRPC se do klienta přidá klientský certifikát, který HttpClientHandler se pak použije k vytvoření klienta gRPC:

public Ticketer.TicketerClient CreateClientWithCert(
    string baseAddress,
    X509Certificate2 certificate)
{
    // Add client cert to the handler
    var handler = new HttpClientHandler();
    handler.ClientCertificates.Add(certificate);

    // Create the gRPC channel
    var channel = GrpcChannel.ForAddress(baseAddress, new GrpcChannelOptions
    {
        HttpHandler = handler
    });

    return new Ticketer.TicketerClient(channel);
}

Další mechanismy ověřování

Mnoho ASP.NET core podporovaných ověřovacích mechanismů funguje s gRPC:

  • Microsoft Entra ID
  • Klientský certifikát
  • IdentityServer
  • JWT Token
  • OAuth 2.0
  • OpenID Connect
  • WS-Federation

Další informace o konfiguraci ověřování na serveru najdete v tématu ASP.NET Základní ověřování.

Konfigurace klienta gRPC pro použití ověřování bude záviset na mechanismu ověřování, který používáte. Předchozí nosný token a příklady klientských certifikátů ukazují několik způsobů, jak lze klienta gRPC nakonfigurovat tak, aby odesílala metadata ověřování pomocí volání gRPC:

  • Klienti gRPC silného typu používají HttpClient interně. Ověřování lze nakonfigurovat na HttpClientHandlernebo přidáním vlastních HttpMessageHandler instancí do .HttpClient
  • Každé volání gRPC má volitelný CallOptions argument. Vlastní hlavičky je možné odeslat pomocí kolekce hlaviček možnosti.

Poznámka:

Ověřování systému Windows (NTLM/ Kerberos/Negotiate) se nedá použít s gRPC. gRPC vyžaduje HTTP/2 a HTTP/2 nepodporuje ověřování systému Windows.

Autorizace uživatelů pro přístup ke službám a metodám služeb

Ve výchozím nastavení můžou všechny metody ve službě volat neověřené uživatele. Pokud chcete vyžadovat ověření, použijte [Authorize] atribut pro službu:

[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
}

Pomocí argumentů a vlastností konstruktoru atributu [Authorize] můžete omezit přístup pouze na uživatele, kteří odpovídají konkrétním zásadám autorizace. Pokud máte například volanou MyAuthorizationPolicyvlastní autorizační zásadu, ujistěte se, že k této službě mají přístup pouze uživatelé odpovídající této zásadě, a to pomocí následujícího kódu:

[Authorize("MyAuthorizationPolicy")]
public class TicketerService : Ticketer.TicketerBase
{
}

Jednotlivé metody služby mohou mít [Authorize] také použitý atribut. Pokud aktuální uživatel neodpovídá zásadám použitým pro metodu i třídu, vrátí se volajícímu chyba:

[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
    public override Task<AvailableTicketsResponse> GetAvailableTickets(
        Empty request, ServerCallContext context)
    {
        // ... buy tickets for the current user ...
    }

    [Authorize("Administrators")]
    public override Task<BuyTicketsResponse> RefundTickets(
        BuyTicketsRequest request, ServerCallContext context)
    {
        // ... refund tickets (something only Administrators can do) ..
    }
}

Další materiály

Zobrazení nebo stažení ukázkového kódu (postup stažení)

Ověřování uživatelů, kteří volají službu gRPC

GRPC lze použít s ověřováním ASP.NET Core k přidružení uživatele k jednotlivým voláním.

Následuje příklad Startup.Configure použití gRPC a ověřování ASP.NET Core:

public void Configure(IApplicationBuilder app)
{
    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGrpcService<GreeterService>();
    });
}

Poznámka:

Pořadí, ve kterém zaregistrujete middleware ověřování ASP.NET Core, záleží. Vždy zavolat UseAuthentication a za a před UseRouting UseEndpoints.UseAuthorization

Ověřovací mechanismus, který vaše aplikace používá během volání, je potřeba nakonfigurovat. Konfigurace ověřování se přidá Startup.ConfigureServices a bude se lišit v závislosti na mechanismu ověřování, který vaše aplikace používá.

Po nastavení ověřování je uživatel přístupný v metodách služby gRPC prostřednictvím ServerCallContextmetody .

public override Task<BuyTicketsResponse> BuyTickets(
    BuyTicketsRequest request, ServerCallContext context)
{
    var user = context.GetHttpContext().User;

    // ... access data from ClaimsPrincipal ...
}

Ověřování nosný token

Klient může poskytnout přístupový token pro ověřování. Server token ověří a použije ho k identifikaci uživatele.

Na serveru se ověřování nosných tokenů konfiguruje pomocí middlewaru JWT Bearer.

V klientovi .NET gRPC lze token odeslat s voláními pomocí Metadata kolekce. Položky v kolekci Metadata se odesílají s voláním gRPC jako hlavičky HTTP:

public bool DoAuthenticatedCall(
    Ticketer.TicketerClient client, string token)
{
    var headers = new Metadata();
    headers.Add("Authorization", $"Bearer {token}");

    var request = new BuyTicketsRequest { Count = 1 };
    var response = await client.BuyTicketsAsync(request, headers);

    return response.Success;
}

Nastavení nosné tokeny pomocí CallCredentials

Konfigurace ChannelCredentials v kanálu představuje alternativní způsob odeslání tokenu do služby pomocí volání gRPC. A ChannelCredentials může zahrnovat CallCredentials, které poskytují způsob, jak automaticky nastavit Metadata.

Výhody použití CallCredentials:

  • Ověřování je centrálně nakonfigurované v kanálu. Token nemusí být ručně poskytnut volání gRPC.
  • CallCredentials.FromInterceptor Zpětné volání je asynchronní. V případě potřeby může volání přihlašovacích údajů načíst token přihlašovacích údajů z externího systému. Asynchronní metody uvnitř zpětného volání by měly používat on CancellationToken AuthInterceptorContext.

Poznámka:

CallCredentials jsou použity pouze v případě, že je kanál zabezpečený protokolem TLS. Odesílání hlaviček ověřování přes nezabezpečené připojení má vliv na zabezpečení a nemělo by se provádět v produkčních prostředích. Aplikace může nakonfigurovat kanál tak, aby toto chování ignoroval a vždy ho používal CallCredentials nastavením UnsafeUseInsecureChannelCallCredentials kanálu.

Přihlašovací údaje v následujícím příkladu konfigurují kanál tak, aby odesílal token s každým voláním gRPC:

private static GrpcChannel CreateAuthenticatedChannel(ITokenProvder tokenProvider)
{
    var credentials = CallCredentials.FromInterceptor(async (context, metadata) =>
    {
        var token = await tokenProvider.GetTokenAsync(context.CancellationToken);
        metadata.Add("Authorization", $"Bearer {token}");
    });

    var channel = GrpcChannel.ForAddress(address, new GrpcChannelOptions
    {
        Credentials = ChannelCredentials.Create(new SslCredentials(), credentials)
    });
    return channel;
}

Nosný token s klientskou továrnou gRPC

Klientská továrna gRPC může vytvářet klienty, kteří odesílají nosný token pomocí AddCallCredentials. Tato metoda je k dispozici v Grpc.Net.ClientFactory verze 2.46.0 nebo novější.

Delegát předaný je AddCallCredentials spuštěn pro každé volání gRPC:

services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
        o.Address = new Uri("https://localhost:5001");
    })
    .AddCallCredentials((context, metadata) =>
    {
        if (!string.IsNullOrEmpty(_token))
        {
            metadata.Add("Authorization", $"Bearer {_token}");
        }
        return Task.CompletedTask;
    });

Injektáž závislostí (DI) lze kombinovat s AddCallCredentials. Přetížení se předá IServiceProvider delegátu, který lze použít k získání služby vytvořené z DI pomocí vymezených a přechodných služeb.

Představte si aplikaci, která má:

  • Uživatelem definovaný ITokenProvider pro získání nosné tokeny. ITokenProvider aplikace is registered in DI with a scoped lifetime.
  • Klientská továrna gRPC je nakonfigurovaná tak, aby vytvářela klienty vložené do služeb gRPC a řadičů webového rozhraní API.
  • Volání gRPC by se měla použít ITokenProvider k získání nosný token.
public interface ITokenProvider
{
    Task<string> GetTokenAsync(CancellationToken cancellationToken);
}

public class AppTokenProvider : ITokenProvider
{
    private string _token;

    public async Task<string> GetTokenAsync(CancellationToken cancellationToken)
    {
        if (_token == null)
        {
            // App code to resolve the token here.
        }

        return _token;
    }
}
services.AddScoped<ITokenProvider, AppTokenProvider>();

services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
        o.Address = new Uri("https://localhost:5001");
    })
    .AddCallCredentials(async (context, metadata, serviceProvider) =>
    {
        var provider = serviceProvider.GetRequiredService<ITokenProvider>();
        var token = await provider.GetTokenAsync(context.CancellationToken);
        metadata.Add("Authorization", $"Bearer {token}");
    }));

Předchozí kód:

  • ITokenProvider Definuje a AppTokenProvider. Tyto typy zpracovávají překlad ověřovacího tokenu pro volání gRPC.
  • Zaregistruje AppTokenProvider typ v oboru životnosti pomocí DI. AppTokenProvider uloží token do mezipaměti, aby se k výpočtu vyžadovalo pouze první volání v oboru.
  • Zaregistruje typ v GreeterClient klientské továrně.
  • Konfiguruje AddCallCredentials pro tohoto klienta. Delegát se spustí při každém volání a přidá token vrácený ITokenProvider do metadat.

Ověřování klientských certifikátů

Klient může případně poskytnout klientský certifikát pro ověřování. Ověřování certifikátů probíhá na úrovni protokolu TLS, dlouho předtím, než se někdy dostane k ASP.NET Core. Když požadavek zadá ASP.NET Core, balíček ověřování klientských certifikátů umožňuje přeložit certifikát na ClaimsPrincipal.

Poznámka:

Nakonfigurujte server tak, aby přijímal klientské certifikáty. Informace o přijetí klientských certifikátů ve Kestrelslužbě , IIS a Azure najdete v tématu Konfigurace ověřování certifikátů v ASP.NET Core.

V klientovi .NET gRPC se do klienta přidá klientský certifikát, který HttpClientHandler se pak použije k vytvoření klienta gRPC:

public Ticketer.TicketerClient CreateClientWithCert(
    string baseAddress,
    X509Certificate2 certificate)
{
    // Add client cert to the handler
    var handler = new HttpClientHandler();
    handler.ClientCertificates.Add(certificate);

    // Create the gRPC channel
    var channel = GrpcChannel.ForAddress(baseAddress, new GrpcChannelOptions
    {
        HttpHandler = handler
    });

    return new Ticketer.TicketerClient(channel);
}

Další mechanismy ověřování

Mnoho ASP.NET core podporovaných ověřovacích mechanismů funguje s gRPC:

  • Microsoft Entra ID
  • Klientský certifikát
  • IdentityServer
  • JWT Token
  • OAuth 2.0
  • OpenID Connect
  • WS-Federation

Další informace o konfiguraci ověřování na serveru najdete v tématu ASP.NET Základní ověřování.

Konfigurace klienta gRPC pro použití ověřování bude záviset na mechanismu ověřování, který používáte. Předchozí nosný token a příklady klientských certifikátů ukazují několik způsobů, jak lze klienta gRPC nakonfigurovat tak, aby odesílala metadata ověřování pomocí volání gRPC:

  • Klienti gRPC silného typu používají HttpClient interně. Ověřování lze nakonfigurovat na HttpClientHandlernebo přidáním vlastních HttpMessageHandler instancí do .HttpClient
  • Každé volání gRPC má volitelný CallOptions argument. Vlastní hlavičky je možné odeslat pomocí kolekce hlaviček možnosti.

Poznámka:

Ověřování systému Windows (NTLM/ Kerberos/Negotiate) se nedá použít s gRPC. gRPC vyžaduje HTTP/2 a HTTP/2 nepodporuje ověřování systému Windows.

Autorizace uživatelů pro přístup ke službám a metodám služeb

Ve výchozím nastavení můžou všechny metody ve službě volat neověřené uživatele. Pokud chcete vyžadovat ověření, použijte [Authorize] atribut pro službu:

[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
}

Pomocí argumentů a vlastností konstruktoru atributu [Authorize] můžete omezit přístup pouze na uživatele, kteří odpovídají konkrétním zásadám autorizace. Pokud máte například volanou MyAuthorizationPolicyvlastní autorizační zásadu, ujistěte se, že k této službě mají přístup pouze uživatelé odpovídající této zásadě, a to pomocí následujícího kódu:

[Authorize("MyAuthorizationPolicy")]
public class TicketerService : Ticketer.TicketerBase
{
}

Jednotlivé metody služby mohou mít [Authorize] také použitý atribut. Pokud aktuální uživatel neodpovídá zásadám použitým pro metodu i třídu, vrátí se volajícímu chyba:

[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
    public override Task<AvailableTicketsResponse> GetAvailableTickets(
        Empty request, ServerCallContext context)
    {
        // ... buy tickets for the current user ...
    }

    [Authorize("Administrators")]
    public override Task<BuyTicketsResponse> RefundTickets(
        BuyTicketsRequest request, ServerCallContext context)
    {
        // ... refund tickets (something only Administrators can do) ..
    }
}

Metody rozšíření autorizace

Autorizaton lze také řídit pomocí standardních metod rozšíření autorizace ASP.NET Core, jako AllowAnonymous jsou a RequireAuthorization.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();

var app = builder.Build();
app.MapGrpcService<TicketerService>().RequireAuthorization("Administrators");
app.Run();

Další materiály