Проверка подлинности и авторизация в gRPC для ASP.NET Core
Примечание.
Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.
Предупреждение
Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в статье о политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 8 этой статьи.
Внимание
Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
В текущем выпуске см . версию .NET 8 этой статьи.
Автор: Джеймс Ньютон-Кинг (James Newton-King)
Просмотреть или скачать образец кода (описание загрузки)
Проверка подлинности пользователей, вызывающих службу gRPC
gRPC можно использовать с проверкой подлинности ASP.NET Core, чтобы связать пользователя с каждым вызовом.
Ниже приведен пример Program.cs
, в котором используется проверка подлинности gRPC и ASP.NET Core:
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapGrpcService<GreeterService>();
Примечание.
Порядок, в котором регистрируется ПО промежуточного слоя ASP.NET Core для проверки подлинности, имеет значение. Всегда вызывайте UseAuthentication
и UseAuthorization
после UseRouting
и до UseEndpoints
.
Механизм проверки подлинности, используемый приложением во время вызова, необходимо настроить. Конфигурация проверки подлинности добавляется в Program.cs
и будет отличаться в зависимости от используемого в приложении механизма проверки подлинности.
После настройки проверки подлинности методы службы gRPC могут получить доступ к пользователю через ServerCallContext
.
public override Task<BuyTicketsResponse> BuyTickets(
BuyTicketsRequest request, ServerCallContext context)
{
var user = context.GetHttpContext().User;
// ... access data from ClaimsPrincipal ...
}
Проверка подлинности маркера носителя
Клиент может предоставить маркер доступа для проверки подлинности. Сервер проверяет маркер и использует его для обнаружения пользователя.
На сервере проверка подлинности маркера носителя настраивается с помощью По промежуточного слоя JWT Bearer.
В клиенте .NET gRPC маркер можно отправить с помощью вызовов с использованием коллекции Metadata
. Записи в коллекции Metadata
отправляются с помощью вызова gRPC в виде заголовков 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;
}
Задайте маркер носителя с помощью CallCredentials
Настройка ChannelCredentials
в канале — это альтернативный способ отправки маркера службе с вызовами gRPC. Класс ChannelCredentials
может содержать класс CallCredentials
, что позволяет автоматически задавать Metadata
.
Преимущества использования CallCredentials
:
- Проверка подлинности централизованно настроена на канале. Маркер не требуется вручную предоставлять вызову gRPC.
- Обратный
CallCredentials.FromInterceptor
вызов является асинхронным. При необходимости учетные данные вызова могут получить маркер учетных данных из внешней системы. Асинхронные методы внутри обратного вызова должны использовать вклCancellationToken
AuthInterceptorContext
.
Примечание.
CallCredentials
применяется только в том случае, если канал защищен протоколом TLS. Отправка заголовков проверки подлинности через небезопасное подключение негативно влияет на безопасность и не должна выполняться в рабочих средах. Приложение может задать параметр UnsafeUseInsecureChannelCallCredentials
в настройках канала, чтобы игнорировать это поведение и всегда использовать CallCredentials
.
Учетные данные в следующем примере настраивают канал для отправки маркера при каждом вызове 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;
}
Создание токена носителя с помощью фабрики клиента gRPC
Фабрика клиента gRPC может создавать клиенты, отправляющие токен носителя с помощью AddCallCredentials
. Этот метод доступен в Grpc.Net.ClientFactory версии 2.46.0 или более поздней.
Переданный делегат AddCallCredentials
выполняется для каждого вызова 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;
});
Внедрение зависимостей можно сочетать с AddCallCredentials
. Перегрузка передает IServiceProvider
в делегат, который можно использовать для получения службы, созданной из внедрения зависимостей, с помощью ограниченных и временных служб.
Рассмотрим приложение, которое имеет:
- Пользовательский
ITokenProvider
для получения токена носителя.ITokenProvider
регистрируется во внедрении зависимостей с заданным временем существования. - Фабрика клиента gRPC настроена для создания клиентов, которые вставляются в службы gRPC и контроллеры веб-API.
- вызовы gRPC должны использовать
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}");
}));
Предыдущий код:
- Создает определения
ITokenProvider
иAppTokenProvider
. Эти типы обрабатывают разрешение маркера проверки подлинности для вызовов gRPC. - Регистрирует тип
AppTokenProvider
для внедрения зависимостей с ограниченным временем существования.AppTokenProvider
кэширует маркер, чтобы его приходилось вычислять только в первом вызове в заданной области. - Регистрирует тип
GreeterClient
в фабрике клиента. - Настраивает
AddCallCredentials
для этого клиента. Делегат выполняется при каждом вызове и добавляет в метаданные маркер, полученный отITokenProvider
.
Проверка подлинности сертификатов клиента
Клиент может также предоставить сертификат клиента для проверки подлинности. Проверка подлинности по сертификату происходит на уровне TLS, задолго до его попадания в ASP.NET Core. Когда запрос попадает в ASP.NET Core, пакет проверки подлинности сертификата клиента позволяет разрешить сертификат в ClaimsPrincipal
.
Примечание.
Сервер должен быть настроен для принятия сертификатов клиентов. Сведения о принятии сертификатов клиента в Kestrel, IIS и Azure см. в разделе Настройка проверки подлинности по сертификату в ASP.NET Core.
В клиенте .NET gRPC сертификат клиента добавляется в HttpClientHandler
, который затем используется для создания клиента 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);
}
Другие механизмы проверки подлинности
Многие механизмы проверки подлинности вASP.NET Core работают с gRPC:
- Microsoft Entra ID
- Сертификат клиента
- IdentityServer
- Маркер JWT
- OAuth 2.0
- OpenID Connect
- WS-Federation
Дополнительные сведения о настройке проверки подлинности на сервере см. в разделе Проверка подлинности в ASP.NET Core.
Настройка клиента gRPC для использования проверки подлинности будет зависеть от используемого механизма проверки подлинности. В предыдущих примерах маркера носителя и сертификата клиента показано несколько способов настройки клиента gRPC для отправки метаданных проверки подлинности с помощью вызовов gRPC:
- Строго типизированные клиенты gRPC используют
HttpClient
внутренне. Проверку подлинности можно настроить с помощью HttpClientHandler или путем добавления пользовательских экземпляров HttpMessageHandler вHttpClient
. - Каждый вызов gRPC имеет необязательный аргумент
CallOptions
. Пользовательские заголовки можно отправлять с помощью коллекции заголовков параметра.
Примечание.
Проверка подлинности Windows (NTLM/Kerberos/Negotiate) не может использоваться с gRPC. Для gRPC требуется HTTP/2, а HTTP/2 не поддерживает проверку подлинности Windows.
Авторизация пользователей для доступа к службам и методам служб
По умолчанию все методы в службе могут вызываться пользователями, не прошедшими проверку подлинности. Чтобы требовать проверку подлинности, примените к службе атрибут [Authorize]
:
[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
}
Можно использовать аргументы конструктора и свойства атрибута [Authorize]
, чтобы ограничить доступ только пользователями, соответствующими определенным политикам авторизации. Например, если имеется пользовательская политика авторизации с именем MyAuthorizationPolicy
, используйте следующий код, чтобы доступ к службе могли получить только пользователи, соответствующие этой политике:
[Authorize("MyAuthorizationPolicy")]
public class TicketerService : Ticketer.TicketerBase
{
}
К отдельным методам службы также может применяться атрибут [Authorize]
. Если текущий пользователь не соответствует политикам, применяемым к методу и классу, вызывающему объекту будет возвращена ошибка:
[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) ..
}
}
Дополнительные ресурсы
Просмотреть или скачать образец кода (описание загрузки)
Проверка подлинности пользователей, вызывающих службу gRPC
gRPC можно использовать с проверкой подлинности ASP.NET Core, чтобы связать пользователя с каждым вызовом.
Ниже приведен пример Startup.Configure
, в котором используется проверка подлинности gRPC и ASP.NET Core:
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
});
}
Примечание.
Порядок, в котором регистрируется ПО промежуточного слоя ASP.NET Core для проверки подлинности, имеет значение. Всегда вызывайте UseAuthentication
и UseAuthorization
после UseRouting
и до UseEndpoints
.
Механизм проверки подлинности, используемый приложением во время вызова, необходимо настроить. Конфигурация проверки подлинности добавляется в Startup.ConfigureServices
и будет отличаться в зависимости от используемого в приложении механизма проверки подлинности.
После настройки проверки подлинности методы службы gRPC могут получить доступ к пользователю через ServerCallContext
.
public override Task<BuyTicketsResponse> BuyTickets(
BuyTicketsRequest request, ServerCallContext context)
{
var user = context.GetHttpContext().User;
// ... access data from ClaimsPrincipal ...
}
Проверка подлинности маркера носителя
Клиент может предоставить маркер доступа для проверки подлинности. Сервер проверяет маркер и использует его для обнаружения пользователя.
На сервере проверка подлинности маркера носителя настраивается с помощью По промежуточного слоя JWT Bearer.
В клиенте .NET gRPC маркер можно отправить с помощью вызовов с использованием коллекции Metadata
. Записи в коллекции Metadata
отправляются с помощью вызова gRPC в виде заголовков 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;
}
Задайте маркер носителя с помощью CallCredentials
Настройка ChannelCredentials
в канале — это альтернативный способ отправки маркера службе с вызовами gRPC. Класс ChannelCredentials
может содержать класс CallCredentials
, что позволяет автоматически задавать Metadata
.
Преимущества использования CallCredentials
:
- Проверка подлинности централизованно настроена на канале. Маркер не требуется вручную предоставлять вызову gRPC.
- Обратный
CallCredentials.FromInterceptor
вызов является асинхронным. При необходимости учетные данные вызова могут получить маркер учетных данных из внешней системы. Асинхронные методы внутри обратного вызова должны использовать вклCancellationToken
AuthInterceptorContext
.
Примечание.
CallCredentials
применяется только в том случае, если канал защищен протоколом TLS. Отправка заголовков проверки подлинности через небезопасное подключение негативно влияет на безопасность и не должна выполняться в рабочих средах. Приложение может задать параметр UnsafeUseInsecureChannelCallCredentials
в настройках канала, чтобы игнорировать это поведение и всегда использовать CallCredentials
.
Учетные данные в следующем примере настраивают канал для отправки маркера при каждом вызове 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;
}
Создание токена носителя с помощью фабрики клиента gRPC
Фабрика клиента gRPC может создавать клиенты, отправляющие токен носителя с помощью AddCallCredentials
. Этот метод доступен в Grpc.Net.ClientFactory версии 2.46.0 или более поздней.
Переданный делегат AddCallCredentials
выполняется для каждого вызова 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;
});
Внедрение зависимостей можно сочетать с AddCallCredentials
. Перегрузка передает IServiceProvider
в делегат, который можно использовать для получения службы, созданной из внедрения зависимостей, с помощью ограниченных и временных служб.
Рассмотрим приложение, которое имеет:
- Пользовательский
ITokenProvider
для получения токена носителя.ITokenProvider
регистрируется во внедрении зависимостей с заданным временем существования. - Фабрика клиента gRPC настроена для создания клиентов, которые вставляются в службы gRPC и контроллеры веб-API.
- вызовы gRPC должны использовать
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}");
}));
Предыдущий код:
- Создает определения
ITokenProvider
иAppTokenProvider
. Эти типы обрабатывают разрешение маркера проверки подлинности для вызовов gRPC. - Регистрирует тип
AppTokenProvider
для внедрения зависимостей с ограниченным временем существования.AppTokenProvider
кэширует маркер, чтобы его приходилось вычислять только в первом вызове в заданной области. - Регистрирует тип
GreeterClient
в фабрике клиента. - Настраивает
AddCallCredentials
для этого клиента. Делегат выполняется при каждом вызове и добавляет в метаданные маркер, полученный отITokenProvider
.
Проверка подлинности сертификатов клиента
Клиент может также предоставить сертификат клиента для проверки подлинности. Проверка подлинности по сертификату происходит на уровне TLS, задолго до его попадания в ASP.NET Core. Когда запрос попадает в ASP.NET Core, пакет проверки подлинности сертификата клиента позволяет разрешить сертификат в ClaimsPrincipal
.
Примечание.
Сервер должен быть настроен для принятия сертификатов клиентов. Сведения о принятии сертификатов клиента в Kestrel, IIS и Azure см. в разделе Настройка проверки подлинности по сертификату в ASP.NET Core.
В клиенте .NET gRPC сертификат клиента добавляется в HttpClientHandler
, который затем используется для создания клиента 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);
}
Другие механизмы проверки подлинности
Многие механизмы проверки подлинности вASP.NET Core работают с gRPC:
- Microsoft Entra ID
- Сертификат клиента
- IdentityServer
- Маркер JWT
- OAuth 2.0
- OpenID Connect
- WS-Federation
Дополнительные сведения о настройке проверки подлинности на сервере см. в разделе Проверка подлинности в ASP.NET Core.
Настройка клиента gRPC для использования проверки подлинности будет зависеть от используемого механизма проверки подлинности. В предыдущих примерах маркера носителя и сертификата клиента показано несколько способов настройки клиента gRPC для отправки метаданных проверки подлинности с помощью вызовов gRPC:
- Строго типизированные клиенты gRPC используют
HttpClient
внутренне. Проверку подлинности можно настроить с помощью HttpClientHandler или путем добавления пользовательских экземпляров HttpMessageHandler вHttpClient
. - Каждый вызов gRPC имеет необязательный аргумент
CallOptions
. Пользовательские заголовки можно отправлять с помощью коллекции заголовков параметра.
Примечание.
Проверка подлинности Windows (NTLM/Kerberos/Negotiate) не может использоваться с gRPC. Для gRPC требуется HTTP/2, а HTTP/2 не поддерживает проверку подлинности Windows.
Авторизация пользователей для доступа к службам и методам служб
По умолчанию все методы в службе могут вызываться пользователями, не прошедшими проверку подлинности. Чтобы требовать проверку подлинности, примените к службе атрибут [Authorize]
:
[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
}
Можно использовать аргументы конструктора и свойства атрибута [Authorize]
, чтобы ограничить доступ только пользователями, соответствующими определенным политикам авторизации. Например, если имеется пользовательская политика авторизации с именем MyAuthorizationPolicy
, используйте следующий код, чтобы доступ к службе могли получить только пользователи, соответствующие этой политике:
[Authorize("MyAuthorizationPolicy")]
public class TicketerService : Ticketer.TicketerBase
{
}
К отдельным методам службы также может применяться атрибут [Authorize]
. Если текущий пользователь не соответствует политикам, применяемым к методу и классу, вызывающему объекту будет возвращена ошибка:
[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) ..
}
}
Методы расширения авторизации
Авторизатон также можно контролировать с помощью стандартных методов расширения авторизации ASP.NET Core, таких как AllowAnonymous
и RequireAuthorization
.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
var app = builder.Build();
app.MapGrpcService<TicketerService>().RequireAuthorization("Administrators");
app.Run();
Дополнительные ресурсы
ASP.NET Core