Delen via


Verificatie en autorisatie in gRPC voor ASP.NET Core

Note

Dit is niet de nieuwste versie van dit artikel. Zie de .NET 9-versie van dit artikel voor de huidige release.

Warning

Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie het .NET- en .NET Core-ondersteuningsbeleid voor meer informatie. Zie de .NET 9-versie van dit artikel voor de huidige release.

Important

Deze informatie heeft betrekking op een pre-releaseproduct dat aanzienlijk kan worden gewijzigd voordat het commercieel wordt uitgebracht. Microsoft geeft geen garanties, uitdrukkelijk of impliciet, met betrekking tot de informatie die hier wordt verstrekt.

Zie de .NET 9-versie van dit artikel voor de huidige release.

Door James Newton-King

Voorbeeldcode weergeven of downloaden(hoe te downloaden)

Gebruikers verifiëren die een gRPC-service aanroepen

gRPC kan worden gebruikt met ASP.NET Core-verificatie om een gebruiker aan elke aanroep te koppelen.

Hier volgt een voorbeeld waarvan Program.cs gRPC en ASP.NET Core-verificatie worden gebruikt:

app.UseRouting();

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

app.MapGrpcService<GreeterService>();

Note

De volgorde waarin u de ASP.NET Core-verificatie-middleware registreert, is van belang. UseAuthentication Bel altijd en na UseAuthorization en UseRouting voorUseEndpoints.

Het verificatiemechanisme dat uw app gebruikt tijdens een aanroep, moet worden geconfigureerd. De verificatieconfiguratie wordt toegevoegd Program.cs en is afhankelijk van het verificatiemechanisme dat uw app gebruikt.

Zodra de verificatie is ingesteld, kan toegang worden verkregen tot de gebruiker in gRPC-servicemethoden via de ServerCallContext.

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

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

Bearer-tokenauthenticatie

De client kan een toegangstoken voor verificatie opgeven. De server valideert het token en gebruikt het om de gebruiker te identificeren.

Op de server wordt bearer-tokenverificatie geconfigureerd met behulp van de JWT Bearer-middleware.

In de .NET gRPC-client kan het token met aanroepen worden verzonden via de Metadata collectie. Vermeldingen in de Metadata verzameling worden verzonden met een gRPC-aanroep als HTTP-headers:

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;
}

Het bearer-token instellen met CallCredentials

Het configureren van ChannelCredentials op een kanaal is een alternatieve manier om het token via gRPC-aanroepen naar de service te verzenden. Een ChannelCredentials kan CallCredentials bevatten, dat een manier biedt om Metadata automatisch in te stellen.

Voordelen van het gebruik CallCredentials:

  • Verificatie is centraal geconfigureerd op het kanaal. Het token hoeft niet handmatig aan de gRPC-aanroep te worden opgegeven.
  • De CallCredentials.FromInterceptor callback is asynchroon. Aanroepen van referenties kunnen een referentietoken ophalen van een extern systeem, indien nodig. Asynchrone methoden in de callback moeten de CancellationToken on AuthInterceptorContextgebruiken.

Note

CallCredentials worden alleen toegepast als het kanaal is beveiligd met TLS. Het verzenden van verificatieheaders via een onveilige verbinding heeft gevolgen voor de beveiliging en moet niet worden uitgevoerd in productieomgevingen. Een app kan een kanaal configureren om dit gedrag te negeren en altijd te gebruiken CallCredentials door in te stellen UnsafeUseInsecureChannelCallCredentials op een kanaal.

De referentie in het volgende voorbeeld configureert het kanaal om het token te verzenden met elke gRPC-aanroep:

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;
}

Bearer-token met gRPC-clientfactory

gRPC-clientfactory kan clients maken die een bearer-token verzenden met behulp van AddCallCredentials. Deze methode is beschikbaar in Grpc.Net.ClientFactory versie 2.46.0 of hoger.

De gemachtigde die aan AddCallCredentials is doorgegeven, wordt uitgevoerd voor elke gRPC-aanroep:

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;
    });

Afhankelijkheidsinjectie (DI) kan worden gecombineerd met AddCallCredentials. Een overload geeft IServiceProvider door aan de delegate, die kan worden gebruikt om een service te verkrijgen die geconstrueerd is met DI en gebruikmaakt van scoped en tijdelijke services.

Overweeg een app met:

  • Door de gebruiker gedefinieerd ITokenProvider voor het ophalen van een bearer token. ITokenProvider is geregistreerd in DI met een gescope levensduur.
  • gRPC-clientfactory is geconfigureerd voor het maken van clients die worden geïnjecteerd in gRPC-services en Web-API-controllers.
  • Voor gRPC-aanroepen moet ITokenProvider worden gebruikt om een bearer-token op te halen.
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}");
    }));

De voorgaande code:

  • Definieert ITokenProvider en AppTokenProvider. Deze typen handelen het oplossen van het verificatietoken voor gRPC-aanroepen af.
  • Registreert het AppTokenProvider type bij DI in een scope-levensduur. AppTokenProvider slaat het token in de cache op, zodat alleen de eerste aanroep in het bereik is vereist om het te berekenen.
  • Registreert het GreeterClient type bij client factory.
  • Configureer AddCallCredentials voor deze client. De gedelegeerde wordt uitgevoerd telkens wanneer er een aanroep wordt gedaan en voegt het token dat wordt geretourneerd door ITokenProvider toe aan de metadata.

Verificatie van clientcertificaten

Een client kan ook een clientcertificaat voor verificatie opgeven. Certificaatverificatie vindt plaats op TLS-niveau, lang voordat het ooit ASP.NET Core wordt. Wanneer de aanvraag binnenkomt in ASP.NET Core, stelt het verificatiepakket voor clientcertificaten u in staat om het certificaat naar een ClaimsPrincipal te herleiden.

Note

Configureer de server om clientcertificaten te accepteren. Zie Kestrel voor informatie over het accepteren van clientcertificaten in IIS en Azure.

In de .NET gRPC-client wordt het clientcertificaat toegevoegd aan HttpClientHandler, dat vervolgens wordt gebruikt om de gRPC-client te maken.

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);
}

Andere verificatiemechanismen

Veel ASP.NET Core ondersteunde verificatiemechanismen werken met gRPC:

  • Microsoft Entra ID
  • Clientcertificaat
  • IdentityServer
  • JWT-token
  • OAuth 2.0
  • OpenID Connect
  • WS-Federation

Zie ASP.NET Core-verificatie voor meer informatie over het configureren van verificatie op de server.

Het configureren van de gRPC-client voor het gebruik van verificatie is afhankelijk van het verificatiemechanisme dat u gebruikt. In de vorige bearer-token- en clientcertificaatvoorbeelden ziet u een aantal manieren waarop de gRPC-client kan worden geconfigureerd voor het verzenden van verificatiemetagegevens met gRPC-aanroepen:

  • Sterk getypte gRPC-clients gebruiken HttpClient intern. Authenticatie kan worden geconfigureerd op HttpClientHandler of door aangepaste HttpMessageHandler exemplaren toe te voegen aan de HttpClient.
  • Elke gRPC-aanroep heeft een optioneel CallOptions argument. Aangepaste headers kunnen worden verzonden met behulp van de verzameling headers van de optie.

Note

Windows-verificatie (NTLM/Kerberos/Negotiate) kan niet worden gebruikt met gRPC. gRPC vereist HTTP/2 en HTTP/2 biedt geen ondersteuning voor Windows-verificatie.

Gebruikers machtigen om toegang te krijgen tot services en servicemethoden

Standaard kunnen alle methoden in een service worden aangeroepen door niet-geverifieerde gebruikers. Als u verificatie wilt vereisen, past u het [Authorize] kenmerk toe op de service:

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

U kunt de constructorargumenten en eigenschappen van het [Authorize] kenmerk gebruiken om de toegang te beperken tot alleen gebruikers die overeenkomen met specifiek autorisatiebeleid. Als u bijvoorbeeld een aangepast autorisatiebeleid hebt met de naam MyAuthorizationPolicy, moet u ervoor zorgen dat alleen gebruikers die overeenkomen met dat beleid toegang hebben tot de service met behulp van de volgende code:

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

Voor afzonderlijke servicemethoden kan ook het [Authorize] kenmerk worden toegepast. Als de huidige gebruiker niet overeenkomt met het beleid dat is toegepast op zowel de methode als de klasse, wordt er een fout geretourneerd naar de aanroeper:

[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) ..
    }
}

Aanvullende bronnen

Voorbeeldcode weergeven of downloaden(hoe te downloaden)

Gebruikers verifiëren die een gRPC-service aanroepen

gRPC kan worden gebruikt met ASP.NET Core-verificatie om een gebruiker aan elke aanroep te koppelen.

Hier volgt een voorbeeld waarvan Startup.Configure gRPC en ASP.NET Core-verificatie worden gebruikt:

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

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

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

Note

De volgorde waarin u de ASP.NET Core-verificatie-middleware registreert, is van belang. UseAuthentication Bel altijd en na UseAuthorization en UseRouting voorUseEndpoints.

Het verificatiemechanisme dat uw app gebruikt tijdens een aanroep, moet worden geconfigureerd. De verificatieconfiguratie wordt toegevoegd Startup.ConfigureServices en is afhankelijk van het verificatiemechanisme dat uw app gebruikt.

Zodra de verificatie is ingesteld, kan toegang worden verkregen tot de gebruiker in gRPC-servicemethoden via de ServerCallContext.

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

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

Bearer-tokenauthenticatie

De client kan een toegangstoken voor verificatie opgeven. De server valideert het token en gebruikt het om de gebruiker te identificeren.

Op de server wordt bearer-tokenverificatie geconfigureerd met behulp van de JWT Bearer-middleware.

In de .NET gRPC-client kan het token met aanroepen worden verzonden via de Metadata collectie. Vermeldingen in de Metadata verzameling worden verzonden met een gRPC-aanroep als HTTP-headers:

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;
}

Het bearer-token instellen met CallCredentials

Het configureren van ChannelCredentials op een kanaal is een alternatieve manier om het token via gRPC-aanroepen naar de service te verzenden. Een ChannelCredentials kan CallCredentials bevatten, dat een manier biedt om Metadata automatisch in te stellen.

Voordelen van het gebruik CallCredentials:

  • Verificatie is centraal geconfigureerd op het kanaal. Het token hoeft niet handmatig aan de gRPC-aanroep te worden opgegeven.
  • De CallCredentials.FromInterceptor callback is asynchroon. Aanroepen van referenties kunnen een referentietoken ophalen van een extern systeem, indien nodig. Asynchrone methoden in de callback moeten de CancellationToken on AuthInterceptorContextgebruiken.

Note

CallCredentials worden alleen toegepast als het kanaal is beveiligd met TLS. Het verzenden van verificatieheaders via een onveilige verbinding heeft gevolgen voor de beveiliging en moet niet worden uitgevoerd in productieomgevingen. Een app kan een kanaal configureren om dit gedrag te negeren en altijd te gebruiken CallCredentials door in te stellen UnsafeUseInsecureChannelCallCredentials op een kanaal.

De referentie in het volgende voorbeeld configureert het kanaal om het token te verzenden met elke gRPC-aanroep:

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;
}

Bearer-token met gRPC-clientfactory

gRPC-clientfactory kan clients maken die een bearer-token verzenden met behulp van AddCallCredentials. Deze methode is beschikbaar in Grpc.Net.ClientFactory versie 2.46.0 of hoger.

De gemachtigde die aan AddCallCredentials is doorgegeven, wordt uitgevoerd voor elke gRPC-aanroep:

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;
    });

Afhankelijkheidsinjectie (DI) kan worden gecombineerd met AddCallCredentials. Een overload geeft IServiceProvider door aan de delegate, die kan worden gebruikt om een service te verkrijgen die geconstrueerd is met DI en gebruikmaakt van scoped en tijdelijke services.

Overweeg een app met:

  • Door de gebruiker gedefinieerd ITokenProvider voor het ophalen van een bearer token. ITokenProvider is geregistreerd in DI met een gescope levensduur.
  • gRPC-clientfactory is geconfigureerd voor het maken van clients die worden geïnjecteerd in gRPC-services en Web-API-controllers.
  • Voor gRPC-aanroepen moet ITokenProvider worden gebruikt om een bearer-token op te halen.
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}");
    }));

De voorgaande code:

  • Definieert ITokenProvider en AppTokenProvider. Deze typen handelen het oplossen van het verificatietoken voor gRPC-aanroepen af.
  • Registreert het AppTokenProvider type bij DI in een scope-levensduur. AppTokenProvider slaat het token in de cache op, zodat alleen de eerste aanroep in het bereik is vereist om het te berekenen.
  • Registreert het GreeterClient type bij client factory.
  • Configureer AddCallCredentials voor deze client. De gedelegeerde wordt uitgevoerd telkens wanneer er een aanroep wordt gedaan en voegt het token dat wordt geretourneerd door ITokenProvider toe aan de metadata.

Verificatie van clientcertificaten

Een client kan ook een clientcertificaat voor verificatie opgeven. Certificaatverificatie vindt plaats op TLS-niveau, lang voordat het ooit ASP.NET Core wordt. Wanneer de aanvraag binnenkomt in ASP.NET Core, stelt het verificatiepakket voor clientcertificaten u in staat om het certificaat naar een ClaimsPrincipal te herleiden.

Note

Configureer de server om clientcertificaten te accepteren. Zie Kestrel voor informatie over het accepteren van clientcertificaten in IIS en Azure.

In de .NET gRPC-client wordt het clientcertificaat toegevoegd aan HttpClientHandler, dat vervolgens wordt gebruikt om de gRPC-client te maken.

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);
}

Andere verificatiemechanismen

Veel ASP.NET Core ondersteunde verificatiemechanismen werken met gRPC:

  • Microsoft Entra ID
  • Clientcertificaat
  • IdentityServer
  • JWT-token
  • OAuth 2.0
  • OpenID Connect
  • WS-Federation

Zie ASP.NET Core-verificatie voor meer informatie over het configureren van verificatie op de server.

Het configureren van de gRPC-client voor het gebruik van verificatie is afhankelijk van het verificatiemechanisme dat u gebruikt. In de vorige bearer-token- en clientcertificaatvoorbeelden ziet u een aantal manieren waarop de gRPC-client kan worden geconfigureerd voor het verzenden van verificatiemetagegevens met gRPC-aanroepen:

  • Sterk getypte gRPC-clients gebruiken HttpClient intern. Authenticatie kan worden geconfigureerd op HttpClientHandler of door aangepaste HttpMessageHandler exemplaren toe te voegen aan de HttpClient.
  • Elke gRPC-aanroep heeft een optioneel CallOptions argument. Aangepaste headers kunnen worden verzonden met behulp van de verzameling headers van de optie.

Note

Windows-verificatie (NTLM/Kerberos/Negotiate) kan niet worden gebruikt met gRPC. gRPC vereist HTTP/2 en HTTP/2 biedt geen ondersteuning voor Windows-verificatie.

Gebruikers machtigen om toegang te krijgen tot services en servicemethoden

Standaard kunnen alle methoden in een service worden aangeroepen door niet-geverifieerde gebruikers. Als u verificatie wilt vereisen, past u het [Authorize] kenmerk toe op de service:

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

U kunt de constructorargumenten en eigenschappen van het [Authorize] kenmerk gebruiken om de toegang te beperken tot alleen gebruikers die overeenkomen met specifiek autorisatiebeleid. Als u bijvoorbeeld een aangepast autorisatiebeleid hebt met de naam MyAuthorizationPolicy, moet u ervoor zorgen dat alleen gebruikers die overeenkomen met dat beleid toegang hebben tot de service met behulp van de volgende code:

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

Voor afzonderlijke servicemethoden kan ook het [Authorize] kenmerk worden toegepast. Als de huidige gebruiker niet overeenkomt met het beleid dat is toegepast op zowel de methode als de klasse, wordt er een fout geretourneerd naar de aanroeper:

[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) ..
    }
}

Methoden voor extensies van autorisatie

Authorizaton kan ook worden beheerd met behulp van standaard-ASP.NET Core-autorisatieuitbreidingsmethoden, zoals AllowAnonymous en RequireAuthorization.

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

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

Aanvullende bronnen