Dela via


Autentisering och auktorisering i gRPC för ASP.NET Core

Note

Det här är inte den senaste versionen av den här artikeln. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Warning

Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i supportpolicyn för .NET och .NET Core. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Important

Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.

För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Av James Newton-King

Visa eller ladda ned exempelkod(ladda ned)

Autentisera användare som anropar en gRPC-tjänst

gRPC kan användas med ASP.NET Core-autentisering för att associera en användare med varje anrop.

Följande är ett exempel som Program.cs använder gRPC- och ASP.NET Core-autentisering:

app.UseRouting();

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

app.MapGrpcService<GreeterService>();

Note

I vilken ordning du registrerar mellanprogrammet för ASP.NET Core-autentisering är det viktigt. Anropa UseAuthentication alltid och UseAuthorization efter UseRouting och före UseEndpoints.

Autentiseringsmekanismen som appen använder under ett anrop måste konfigureras. Autentiseringskonfigurationen läggs till i Program.cs och skiljer sig beroende på vilken autentiseringsmekanism din app använder.

När autentiseringen har konfigurerats kan användaren nås i en gRPC-tjänstmetod via ServerCallContext.

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

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

Autentisering med ägartoken

Klienten kan tillhandahålla en åtkomsttoken för autentisering. Servern verifierar token och använder den för att identifiera användaren.

På servern konfigureras autentisering av ägartoken med hjälp av JWT Bearer-mellanprogrammet.

I .NET gRPC-klienten kan token skickas med anrop genom att använda samlingen Metadata. Poster i Metadata-samlingen skickas med ett gRPC-anrop som HTTP-huvuden.

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

Ange ägartoken med CallCredentials

Konfigurera ChannelCredentials på en kanal är ett alternativt sätt att skicka token till tjänsten med gRPC-anrop. En ChannelCredentials kan innehålla CallCredentials, som ger ett sätt att automatiskt ange Metadata.

Fördelar med att använda CallCredentials:

  • Autentiseringen är centralt konfigurerad på kanalen. Token behöver inte anges manuellt till gRPC-anropet.
  • Återanropet CallCredentials.FromInterceptor är asynkront. Anropsuppgifter för autentisering kan hämta en autentiseringstoken från ett externt system om det behövs. Asynkrona metoder i återanropet ska använda CancellationTokenAuthInterceptorContext.

Note

CallCredentials tillämpas endast om kanalen skyddas med TLS. Att skicka autentiseringshuvuden via en osäker anslutning har säkerhetskonsekvenser och bör inte göras i produktionsmiljöer. En app kan konfigurera en kanal för att ignorera det här beteendet och alltid använda CallCredentials genom att ange UnsafeUseInsecureChannelCallCredentials på en kanal.

Autentiseringsuppgifterna i följande exempel konfigurerar kanalen för att skicka token med varje gRPC-anrop:

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

Ägartoken med gRPC-klientfabrik

gRPC-klientfabriken kan skapa klienter som skickar en bärartoken med AddCallCredentials. Den här metoden är tillgänglig i Grpc.Net.ClientFactory version 2.46.0 eller senare.

Delegaten som skickas till AddCallCredentials körs för varje gRPC-anrop.

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

Beroendeinjektion (DI) kan kombineras med AddCallCredentials. En överlagring skickas IServiceProvider till ombudet, som kan användas för att hämta en tjänst som konstruerats från DI med hjälp av begränsade och tillfälliga tjänster.

Överväg en app som har:

  • En användardefinierad ITokenProvider för att hämta en bärartoken. ITokenProvider är registrerad i DI med en begränsad livstid.
  • gRPC-klientfabriken är konfigurerad för att skapa klienter som matas in i gRPC-tjänster och webb-API-styrenheter.
  • gRPC-anrop bör använda ITokenProvider för att hämta en bärartoken.
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}");
    }));

Föregående kod:

  • Definierar ITokenProvider och AppTokenProvider. Dessa typer hanterar matchning av autentiseringstoken för gRPC-anrop.
  • Registrerar typen AppTokenProvider med DI med en avgränsad livstid. AppTokenProvider cachelagrar token så att endast det första anropet i omfånget krävs för att beräkna den.
  • Registrerar GreeterClient-typen med klientfabriken.
  • Konfigurerar AddCallCredentials för den här klienten. Delegaten körs varje gång ett anrop görs och lägger till den token som returneras av ITokenProvider till metadata.

Autentisering av klientcertifikat

En klient kan också tillhandahålla ett klientcertifikat för autentisering. Certifikatautentisering sker på TLS-nivå, långt innan det någonsin kommer till ASP.NET Core. När begäran kommer in i ASP.NET Core möjliggör autentiseringspaketet för klientcertifikatet att du kan lösa certifikatet till en ClaimsPrincipal.

Note

Konfigurera servern för att acceptera klientcertifikat. Information om hur du accepterar klientcertifikat i Kestrel, IIS och Azure finns i Konfigurera certifikatautentisering i ASP.NET Core.

I .NET gRPC-klienten läggs klientcertifikatet till HttpClientHandler som sedan används för att skapa gRPC-klienten:

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

Andra autentiseringsmekanismer

Många ASP.NET Core-autentiseringsmekanismer som stöds fungerar med gRPC:

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

Mer information om hur du konfigurerar autentisering på servern finns i ASP.NET Core-autentisering.

Om du konfigurerar gRPC-klienten så att den använder autentisering beror det på vilken autentiseringsmekanism du använder. Föregående exempel på ägartoken och klientcertifikat visar ett par sätt som gRPC-klienten kan konfigureras för att skicka autentiseringsmetadata med gRPC-anrop:

  • Starkt skrivna gRPC-klienter använder HttpClient internt. Autentisering kan konfigureras på HttpClientHandlereller genom att lägga till anpassade HttpMessageHandler instanser i HttpClient.
  • Varje gRPC-anrop har ett valfritt CallOptions argument. Anpassade rubriker kan skickas med hjälp av alternativets samling rubriker.

Note

Windows-autentisering (NTLM/Kerberos/Negotiate) kan inte användas med gRPC. gRPC kräver HTTP/2 och HTTP/2 stöder inte Windows-autentisering.

Auktorisera användare att komma åt tjänster och tjänstmetoder

Som standard kan alla metoder i en tjänst anropas av oautentiserade användare. Använd attributet för tjänsten för att kräva autentisering [Authorize] :

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

Du kan använda konstruktorargumenten och egenskaperna för attributet för att begränsa åtkomsten [Authorize] till endast användare som matchar specifika auktoriseringsprinciper. Om du till exempel har en anpassad auktoriseringsprincip med namnet MyAuthorizationPolicykontrollerar du att endast användare som matchar den principen kan komma åt tjänsten med hjälp av följande kod:

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

Enskilda tjänstmetoder kan också ha attributet [Authorize] tillämpat. Om den aktuella användaren inte matchar de principer som tillämpas på både metoden och klassen returneras ett fel till anroparen:

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

Ytterligare resurser

Visa eller ladda ned exempelkod(ladda ned)

Autentisera användare som anropar en gRPC-tjänst

gRPC kan användas med ASP.NET Core-autentisering för att associera en användare med varje anrop.

Följande är ett exempel som Startup.Configure använder gRPC- och ASP.NET Core-autentisering:

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

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

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

Note

I vilken ordning du registrerar mellanprogrammet för ASP.NET Core-autentisering är det viktigt. Anropa UseAuthentication alltid och UseAuthorization efter UseRouting och före UseEndpoints.

Autentiseringsmekanismen som appen använder under ett anrop måste konfigureras. Autentiseringskonfigurationen läggs till i Startup.ConfigureServices och skiljer sig beroende på vilken autentiseringsmekanism din app använder.

När autentiseringen har konfigurerats kan användaren nås i en gRPC-tjänstmetod via ServerCallContext.

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

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

Autentisering med ägartoken

Klienten kan tillhandahålla en åtkomsttoken för autentisering. Servern verifierar token och använder den för att identifiera användaren.

På servern konfigureras autentisering av ägartoken med hjälp av JWT Bearer-mellanprogrammet.

I .NET gRPC-klienten kan token skickas med anrop genom att använda samlingen Metadata. Poster i Metadata-samlingen skickas med ett gRPC-anrop som HTTP-huvuden.

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

Ange ägartoken med CallCredentials

Konfigurera ChannelCredentials på en kanal är ett alternativt sätt att skicka token till tjänsten med gRPC-anrop. En ChannelCredentials kan innehålla CallCredentials, som ger ett sätt att automatiskt ange Metadata.

Fördelar med att använda CallCredentials:

  • Autentiseringen är centralt konfigurerad på kanalen. Token behöver inte anges manuellt till gRPC-anropet.
  • Återanropet CallCredentials.FromInterceptor är asynkront. Anropsuppgifter för autentisering kan hämta en autentiseringstoken från ett externt system om det behövs. Asynkrona metoder i återanropet ska använda CancellationTokenAuthInterceptorContext.

Note

CallCredentials tillämpas endast om kanalen skyddas med TLS. Att skicka autentiseringshuvuden via en osäker anslutning har säkerhetskonsekvenser och bör inte göras i produktionsmiljöer. En app kan konfigurera en kanal för att ignorera det här beteendet och alltid använda CallCredentials genom att ange UnsafeUseInsecureChannelCallCredentials på en kanal.

Autentiseringsuppgifterna i följande exempel konfigurerar kanalen för att skicka token med varje gRPC-anrop:

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

Ägartoken med gRPC-klientfabrik

gRPC-klientfabriken kan skapa klienter som skickar en bärartoken med AddCallCredentials. Den här metoden är tillgänglig i Grpc.Net.ClientFactory version 2.46.0 eller senare.

Delegaten som skickas till AddCallCredentials körs för varje gRPC-anrop.

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

Beroendeinjektion (DI) kan kombineras med AddCallCredentials. En överlagring skickas IServiceProvider till ombudet, som kan användas för att hämta en tjänst som konstruerats från DI med hjälp av begränsade och tillfälliga tjänster.

Överväg en app som har:

  • En användardefinierad ITokenProvider för att hämta en bärartoken. ITokenProvider är registrerad i DI med en begränsad livstid.
  • gRPC-klientfabriken är konfigurerad för att skapa klienter som matas in i gRPC-tjänster och webb-API-styrenheter.
  • gRPC-anrop bör använda ITokenProvider för att hämta en bärartoken.
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}");
    }));

Föregående kod:

  • Definierar ITokenProvider och AppTokenProvider. Dessa typer hanterar matchning av autentiseringstoken för gRPC-anrop.
  • Registrerar typen AppTokenProvider med DI med en avgränsad livstid. AppTokenProvider cachelagrar token så att endast det första anropet i omfånget krävs för att beräkna den.
  • Registrerar GreeterClient-typen med klientfabriken.
  • Konfigurerar AddCallCredentials för den här klienten. Delegaten körs varje gång ett anrop görs och lägger till den token som returneras av ITokenProvider till metadata.

Autentisering av klientcertifikat

En klient kan också tillhandahålla ett klientcertifikat för autentisering. Certifikatautentisering sker på TLS-nivå, långt innan det någonsin kommer till ASP.NET Core. När begäran kommer in i ASP.NET Core möjliggör autentiseringspaketet för klientcertifikatet att du kan lösa certifikatet till en ClaimsPrincipal.

Note

Konfigurera servern för att acceptera klientcertifikat. Information om hur du accepterar klientcertifikat i Kestrel, IIS och Azure finns i Konfigurera certifikatautentisering i ASP.NET Core.

I .NET gRPC-klienten läggs klientcertifikatet till HttpClientHandler som sedan används för att skapa gRPC-klienten:

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

Andra autentiseringsmekanismer

Många ASP.NET Core-autentiseringsmekanismer som stöds fungerar med gRPC:

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

Mer information om hur du konfigurerar autentisering på servern finns i ASP.NET Core-autentisering.

Om du konfigurerar gRPC-klienten så att den använder autentisering beror det på vilken autentiseringsmekanism du använder. Föregående exempel på ägartoken och klientcertifikat visar ett par sätt som gRPC-klienten kan konfigureras för att skicka autentiseringsmetadata med gRPC-anrop:

  • Starkt skrivna gRPC-klienter använder HttpClient internt. Autentisering kan konfigureras på HttpClientHandlereller genom att lägga till anpassade HttpMessageHandler instanser i HttpClient.
  • Varje gRPC-anrop har ett valfritt CallOptions argument. Anpassade rubriker kan skickas med hjälp av alternativets samling rubriker.

Note

Windows-autentisering (NTLM/Kerberos/Negotiate) kan inte användas med gRPC. gRPC kräver HTTP/2 och HTTP/2 stöder inte Windows-autentisering.

Auktorisera användare att komma åt tjänster och tjänstmetoder

Som standard kan alla metoder i en tjänst anropas av oautentiserade användare. Använd attributet för tjänsten för att kräva autentisering [Authorize] :

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

Du kan använda konstruktorargumenten och egenskaperna för attributet för att begränsa åtkomsten [Authorize] till endast användare som matchar specifika auktoriseringsprinciper. Om du till exempel har en anpassad auktoriseringsprincip med namnet MyAuthorizationPolicykontrollerar du att endast användare som matchar den principen kan komma åt tjänsten med hjälp av följande kod:

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

Enskilda tjänstmetoder kan också ha attributet [Authorize] tillämpat. Om den aktuella användaren inte matchar de principer som tillämpas på både metoden och klassen returneras ett fel till anroparen:

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

Metoder för auktoriseringstillägg

Authorizaton kan också styras med standardmetoder för ASP.NET Core-auktoriseringstillägg, till exempel AllowAnonymous och RequireAuthorization.

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

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

Ytterligare resurser