Aracılığıyla paylaş


ASP.NET Core için gRPC'de kimlik doğrulaması ve yetkilendirme

Yayınlayan James Newton-King

Örnek kodu görüntüleme veya indirme (nasıl indirilir)

gRPC hizmetini çağıran kullanıcıların kimliğini doğrulama

gRPC, bir kullanıcıyı her çağrıyla ilişkilendirmek için ASP.NET Core kimlik doğrulaması ile kullanılabilir.

Aşağıda gRPC ve ASP.NET Core kimlik doğrulaması kullanan bir örnek Program.cs verilmiştir:

app.UseRouting();

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

app.MapGrpcService<GreeterService>();

Not

ASP.NET Core kimlik doğrulama ara yazılımını kaydetme sırası önemlidir. Her zaman ve UseAuthorization sonrasında UseRouting ve öncesinde UseEndpointsöğesini arayınUseAuthentication.

Uygulamanızın çağrı sırasında kullandığı kimlik doğrulama mekanizmasının yapılandırılması gerekir. kimlik doğrulama yapılandırması eklenir Program.cs ve uygulamanızın kullandığı kimlik doğrulama mekanizmasına bağlı olarak farklı olacaktır.

Kimlik doğrulaması ayarlandıktan sonra, kullanıcı aracılığıyla bir gRPC hizmet yöntemlerinde ServerCallContexterişilebilir.

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

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

Taşıyıcı belirteç kimlik doğrulaması

İstemci, kimlik doğrulaması için bir erişim belirteci sağlayabilir. Sunucu belirteci doğrular ve kullanıcıyı tanımlamak için kullanır.

Sunucuda taşıyıcı belirteç kimlik doğrulaması JWT Taşıyıcı ara yazılımı kullanılarak yapılandırılır.

.NET gRPC istemcisinde belirteç, koleksiyonu kullanılarak Metadata çağrılarla gönderilebilir. Koleksiyondaki Metadata girdiler http üst bilgileri olarak gRPC çağrısıyla gönderilir:

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

Taşıyıcı belirtecini ile ayarlama CallCredentials

Bir kanalda yapılandırma ChannelCredentials , belirteci gRPC çağrılarıyla hizmete göndermenin alternatif bir yoludur. , ChannelCredentials öğesini otomatik olarak ayarlamak Metadataiçin bir yol sağlayan öğesini içerebilirCallCredentials.

kullanmanın CallCredentialsavantajları:

  • Kimlik doğrulaması kanalda merkezi olarak yapılandırılır. Belirtecin gRPC çağrısına el ile sağlanması gerekmez.
  • Geri CallCredentials.FromInterceptor çağırma zaman uyumsuzdur. Çağrı kimlik bilgileri gerekirse bir dış sistemden kimlik bilgisi belirteci getirebilir. Geri çağırma içindeki zaman uyumsuz yöntemler üzerinde AuthInterceptorContextkullanmalıdırCancellationToken.

Not

CallCredentials yalnızca kanalın GÜVENLIĞI TLS ile sağlandığında uygulanır. Güvenli olmayan bir bağlantı üzerinden kimlik doğrulama üst bilgileri göndermenin güvenlik açısından etkileri vardır ve üretim ortamlarında yapılmamalıdır. Bir uygulama, kanalı bu davranışı yoksayacak şekilde yapılandırabilir ve her zaman kanalda ayar UnsafeUseInsecureChannelCallCredentials yaparak kullanabilirCallCredentials.

Aşağıdaki örnekteki kimlik bilgisi, kanalı her gRPC çağrısıyla belirteci gönderecek şekilde yapılandırıyor:

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

gRPC istemci fabrikası ile taşıyıcı belirteci

gRPC istemci fabrikası kullanarak AddCallCredentialstaşıyıcı belirteç gönderen istemciler oluşturabilir. Bu yöntem Grpc.Net.ClientFactory 2.46.0 veya sonraki bir sürümde kullanılabilir.

geçirilen AddCallCredentials temsilci her gRPC çağrısı için yürütülür:

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

Bağımlılık ekleme (DI) ile AddCallCredentialsbirleştirilebilir. Aşırı yükleme, kapsamlı ve geçici hizmetler kullanılarak DI'den bir hizmet oluşturmak için kullanılabilen temsilciye geçerIServiceProvider.

Aşağıdakilere sahip bir uygulamayı düşünün:

  • Taşıyıcı belirteci almak için kullanıcı tanımlı ITokenProvider . ITokenProvider , kapsamlı bir yaşam süresiyle DI'ye kaydedilir.
  • gRPC istemci fabrikası, gRPC hizmetlerine ve Web API denetleyicilerine eklenen istemcileri oluşturmak için yapılandırılır.
  • gRPC çağrıları taşıyıcı belirteci almak için kullanmalıdır ITokenProvider .
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}");
    }));

Yukarıdaki kod:

  • ve AppTokenProvideröğesini tanımlarITokenProvider. Bu türler gRPC çağrıları için kimlik doğrulama belirtecini çözümlemeyi işler.
  • AppTokenProvider Türü kapsamlı bir yaşam süresi içinde DI'ye kaydeder. AppTokenProvider belirteci önbelleğe alır, böylece yalnızca kapsamdaki ilk çağrının hesaplanması gerekir.
  • Türü istemci fabrikasına GreeterClient kaydeder.
  • Bu istemci için yapılandırılır AddCallCredentials . Temsilci her çağrı yapıldığında yürütülür ve tarafından ITokenProvider döndürülen belirteci meta veriye ekler.

İstemci sertifikası kimlik doğrulaması

İstemci alternatif olarak kimlik doğrulaması için bir istemci sertifikası sağlayabilir. Sertifika kimlik doğrulaması , ASP.NET Core'a varmadan çok daha önce TLS düzeyinde gerçekleşir. İstek ASP.NET Core'a girdiğinde, istemci sertifikası kimlik doğrulama paketi sertifikayı bir ClaimsPrincipalolarak çözümlemenize olanak tanır.

Not

Sunucuyu istemci sertifikalarını kabul etmek için yapılandırın. , IIS ve Azure'da Kestrelistemci sertifikalarını kabul etme hakkında bilgi için bkz . ASP.NET Core'da sertifika kimlik doğrulamasını yapılandırma.

.NET gRPC istemcisinde, daha sonra gRPC istemcisini oluşturmak için kullanılan istemci sertifikası eklenir HttpClientHandler :

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

Diğer kimlik doğrulama mekanizmaları

Birçok ASP.NET Core destekli kimlik doğrulama mekanizması gRPC ile çalışır:

  • Microsoft Entra Kimlik
  • İstemci Sertifikası
  • IdentitySunucu
  • JWT Belirteci
  • OAuth 2.0
  • OpenID Connect
  • WS-Federation

Sunucuda kimlik doğrulamasını yapılandırma hakkında daha fazla bilgi için bkz . ASP.NET Çekirdek kimlik doğrulaması.

gRPC istemcisini kimlik doğrulaması kullanacak şekilde yapılandırmak, kullandığınız kimlik doğrulama mekanizmasına bağlıdır. Önceki taşıyıcı belirteci ve istemci sertifikası örnekleri, gRPC istemcisinin gRPC çağrılarıyla kimlik doğrulama meta verilerini gönderecek şekilde yapılandırılmasının birkaç yolunu gösterir:

  • Kesin olarak yazılan gRPC istemcileri dahili olarak kullanır HttpClient . Kimlik doğrulaması üzerinde HttpClientHandlerveya öğesine özel HttpMessageHandler örnekler HttpClienteklenerek yapılandırılabilir.
  • Her gRPC çağrısının isteğe bağlı CallOptions bir bağımsız değişkeni vardır. Özel üst bilgiler seçeneğin üst bilgi koleksiyonu kullanılarak gönderilebilir.

Not

Windows Kimlik Doğrulaması (NTLM/Kerberos/Negotiate) gRPC ile kullanılamaz. gRPC HTTP/2 gerektirir ve HTTP/2, Windows Kimlik Doğrulamayı desteklemez.

Kullanıcılara hizmetlere ve hizmet yöntemlerine erişme yetkisi verme

Varsayılan olarak, bir hizmetteki tüm yöntemler kimliği doğrulanmamış kullanıcılar tarafından çağrılabilir. Kimlik doğrulaması gerektirmek için özniteliğini [Authorize] hizmete uygulayın:

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

Yalnızca belirli yetkilendirme ilkeleriyle eşleşen kullanıcılara erişimi kısıtlamak için özniteliğin [Authorize] oluşturucu bağımsız değişkenlerini ve özelliklerini kullanabilirsiniz. Örneğin, adlı MyAuthorizationPolicyözel bir yetkilendirme ilkeniz varsa, yalnızca bu ilkeyle eşleşen kullanıcıların aşağıdaki kodu kullanarak hizmete erişebildiğinden emin olun:

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

Tek tek hizmet yöntemlerinde [Authorize] de özniteliği uygulanabilir. Geçerli kullanıcı hem yönteme hem de sınıfa uygulanan ilkeler ile eşleşmiyorsa, çağırana bir hata döndürülür:

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

Ek kaynaklar

Örnek kodu görüntüleme veya indirme (nasıl indirilir)

gRPC hizmetini çağıran kullanıcıların kimliğini doğrulama

gRPC, bir kullanıcıyı her çağrıyla ilişkilendirmek için ASP.NET Core kimlik doğrulaması ile kullanılabilir.

Aşağıda gRPC ve ASP.NET Core kimlik doğrulaması kullanan bir örnek Startup.Configure verilmiştir:

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

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

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

Not

ASP.NET Core kimlik doğrulama ara yazılımını kaydetme sırası önemlidir. Her zaman ve UseAuthorization sonrasında UseRouting ve öncesinde UseEndpointsöğesini arayınUseAuthentication.

Uygulamanızın çağrı sırasında kullandığı kimlik doğrulama mekanizmasının yapılandırılması gerekir. kimlik doğrulama yapılandırması eklenir Startup.ConfigureServices ve uygulamanızın kullandığı kimlik doğrulama mekanizmasına bağlı olarak farklı olacaktır.

Kimlik doğrulaması ayarlandıktan sonra, kullanıcı aracılığıyla bir gRPC hizmet yöntemlerinde ServerCallContexterişilebilir.

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

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

Taşıyıcı belirteç kimlik doğrulaması

İstemci, kimlik doğrulaması için bir erişim belirteci sağlayabilir. Sunucu belirteci doğrular ve kullanıcıyı tanımlamak için kullanır.

Sunucuda taşıyıcı belirteç kimlik doğrulaması JWT Taşıyıcı ara yazılımı kullanılarak yapılandırılır.

.NET gRPC istemcisinde belirteç, koleksiyonu kullanılarak Metadata çağrılarla gönderilebilir. Koleksiyondaki Metadata girdiler http üst bilgileri olarak gRPC çağrısıyla gönderilir:

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

Taşıyıcı belirtecini ile ayarlama CallCredentials

Bir kanalda yapılandırma ChannelCredentials , belirteci gRPC çağrılarıyla hizmete göndermenin alternatif bir yoludur. , ChannelCredentials öğesini otomatik olarak ayarlamak Metadataiçin bir yol sağlayan öğesini içerebilirCallCredentials.

kullanmanın CallCredentialsavantajları:

  • Kimlik doğrulaması kanalda merkezi olarak yapılandırılır. Belirtecin gRPC çağrısına el ile sağlanması gerekmez.
  • Geri CallCredentials.FromInterceptor çağırma zaman uyumsuzdur. Çağrı kimlik bilgileri gerekirse bir dış sistemden kimlik bilgisi belirteci getirebilir. Geri çağırma içindeki zaman uyumsuz yöntemler üzerinde AuthInterceptorContextkullanmalıdırCancellationToken.

Not

CallCredentials yalnızca kanalın GÜVENLIĞI TLS ile sağlandığında uygulanır. Güvenli olmayan bir bağlantı üzerinden kimlik doğrulama üst bilgileri göndermenin güvenlik açısından etkileri vardır ve üretim ortamlarında yapılmamalıdır. Bir uygulama, kanalı bu davranışı yoksayacak şekilde yapılandırabilir ve her zaman kanalda ayar UnsafeUseInsecureChannelCallCredentials yaparak kullanabilirCallCredentials.

Aşağıdaki örnekteki kimlik bilgisi, kanalı her gRPC çağrısıyla belirteci gönderecek şekilde yapılandırıyor:

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

gRPC istemci fabrikası ile taşıyıcı belirteci

gRPC istemci fabrikası kullanarak AddCallCredentialstaşıyıcı belirteç gönderen istemciler oluşturabilir. Bu yöntem Grpc.Net.ClientFactory 2.46.0 veya sonraki bir sürümde kullanılabilir.

geçirilen AddCallCredentials temsilci her gRPC çağrısı için yürütülür:

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

Bağımlılık ekleme (DI) ile AddCallCredentialsbirleştirilebilir. Aşırı yükleme, kapsamlı ve geçici hizmetler kullanılarak DI'den bir hizmet oluşturmak için kullanılabilen temsilciye geçerIServiceProvider.

Aşağıdakilere sahip bir uygulamayı düşünün:

  • Taşıyıcı belirteci almak için kullanıcı tanımlı ITokenProvider . ITokenProvider , kapsamlı bir yaşam süresiyle DI'ye kaydedilir.
  • gRPC istemci fabrikası, gRPC hizmetlerine ve Web API denetleyicilerine eklenen istemcileri oluşturmak için yapılandırılır.
  • gRPC çağrıları taşıyıcı belirteci almak için kullanmalıdır ITokenProvider .
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}");
    }));

Yukarıdaki kod:

  • ve AppTokenProvideröğesini tanımlarITokenProvider. Bu türler gRPC çağrıları için kimlik doğrulama belirtecini çözümlemeyi işler.
  • AppTokenProvider Türü kapsamlı bir yaşam süresi içinde DI'ye kaydeder. AppTokenProvider belirteci önbelleğe alır, böylece yalnızca kapsamdaki ilk çağrının hesaplanması gerekir.
  • Türü istemci fabrikasına GreeterClient kaydeder.
  • Bu istemci için yapılandırılır AddCallCredentials . Temsilci her çağrı yapıldığında yürütülür ve tarafından ITokenProvider döndürülen belirteci meta veriye ekler.

İstemci sertifikası kimlik doğrulaması

İstemci alternatif olarak kimlik doğrulaması için bir istemci sertifikası sağlayabilir. Sertifika kimlik doğrulaması , ASP.NET Core'a varmadan çok daha önce TLS düzeyinde gerçekleşir. İstek ASP.NET Core'a girdiğinde, istemci sertifikası kimlik doğrulama paketi sertifikayı bir ClaimsPrincipalolarak çözümlemenize olanak tanır.

Not

Sunucuyu istemci sertifikalarını kabul etmek için yapılandırın. , IIS ve Azure'da Kestrelistemci sertifikalarını kabul etme hakkında bilgi için bkz . ASP.NET Core'da sertifika kimlik doğrulamasını yapılandırma.

.NET gRPC istemcisinde, daha sonra gRPC istemcisini oluşturmak için kullanılan istemci sertifikası eklenir HttpClientHandler :

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

Diğer kimlik doğrulama mekanizmaları

Birçok ASP.NET Core destekli kimlik doğrulama mekanizması gRPC ile çalışır:

  • Microsoft Entra Kimlik
  • İstemci Sertifikası
  • IdentitySunucu
  • JWT Belirteci
  • OAuth 2.0
  • OpenID Connect
  • WS-Federation

Sunucuda kimlik doğrulamasını yapılandırma hakkında daha fazla bilgi için bkz . ASP.NET Çekirdek kimlik doğrulaması.

gRPC istemcisini kimlik doğrulaması kullanacak şekilde yapılandırmak, kullandığınız kimlik doğrulama mekanizmasına bağlıdır. Önceki taşıyıcı belirteci ve istemci sertifikası örnekleri, gRPC istemcisinin gRPC çağrılarıyla kimlik doğrulama meta verilerini gönderecek şekilde yapılandırılmasının birkaç yolunu gösterir:

  • Kesin olarak yazılan gRPC istemcileri dahili olarak kullanır HttpClient . Kimlik doğrulaması üzerinde HttpClientHandlerveya öğesine özel HttpMessageHandler örnekler HttpClienteklenerek yapılandırılabilir.
  • Her gRPC çağrısının isteğe bağlı CallOptions bir bağımsız değişkeni vardır. Özel üst bilgiler seçeneğin üst bilgi koleksiyonu kullanılarak gönderilebilir.

Not

Windows Kimlik Doğrulaması (NTLM/Kerberos/Negotiate) gRPC ile kullanılamaz. gRPC HTTP/2 gerektirir ve HTTP/2, Windows Kimlik Doğrulamayı desteklemez.

Kullanıcılara hizmetlere ve hizmet yöntemlerine erişme yetkisi verme

Varsayılan olarak, bir hizmetteki tüm yöntemler kimliği doğrulanmamış kullanıcılar tarafından çağrılabilir. Kimlik doğrulaması gerektirmek için özniteliğini [Authorize] hizmete uygulayın:

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

Yalnızca belirli yetkilendirme ilkeleriyle eşleşen kullanıcılara erişimi kısıtlamak için özniteliğin [Authorize] oluşturucu bağımsız değişkenlerini ve özelliklerini kullanabilirsiniz. Örneğin, adlı MyAuthorizationPolicyözel bir yetkilendirme ilkeniz varsa, yalnızca bu ilkeyle eşleşen kullanıcıların aşağıdaki kodu kullanarak hizmete erişebildiğinden emin olun:

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

Tek tek hizmet yöntemlerinde [Authorize] de özniteliği uygulanabilir. Geçerli kullanıcı hem yönteme hem de sınıfa uygulanan ilkeler ile eşleşmiyorsa, çağırana bir hata döndürülür:

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

Ek kaynaklar