Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Note
Это не последняя версия этой статьи. В текущей версии см. версию .NET 10 этой статьи.
Warning
Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущей версии см. версию .NET 10 этой статьи.
Автор: Джеймс Ньютон-Кинг (James Newton-King)
Просмотреть или скачать образец кода (описание загрузки)
Проверка подлинности пользователей, вызывающих службу gRPC
gRPC можно использовать с проверкой подлинности ASP.NET Core, чтобы связать пользователя с каждым вызовом.
Ниже приведен пример Program.cs, в котором используется проверка подлинности gRPC и ASP.NET Core:
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapGrpcService<GreeterService>();
Note
Порядок, в котором вы регистрируете ASP.NET Core middleware для аутентификации, имеет значение. Всегда вызывайте 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.
Note
CallCredentials применяется только в том случае, если канал защищен протоколом TLS. Отправка заголовков проверки подлинности через небезопасное подключение негативно влияет на безопасность и не должна выполняться в рабочих средах. Приложение может задать параметр CallCredentials в настройках канала, чтобы игнорировать это поведение и всегда использовать UnsafeUseInsecureChannelCallCredentials.
Учетные данные доступа в следующем примере настраивают канал связи для отправки токена при каждом вызове 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 в делегат, который можно использовать для получения службы, созданной с использованием DI, с помощью служб ограниченной и временной области действия.
Рассмотрим приложение, которое имеет:
- Пользовательский
ITokenProviderдля получения токена носителя.ITokenProviderрегистрируется в DI (внедрение зависимостей) с временной областью. - Фабрика клиента 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.
Note
Сервер должен быть настроен для принятия сертификатов клиентов. Сведения о принятии сертификатов клиента в 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. Пользовательские заголовки можно отправлять с помощью коллекции заголовков опции.
Note
Проверка подлинности 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>();
});
}
Note
Порядок, в котором вы регистрируете ASP.NET Core middleware для аутентификации, имеет значение. Всегда вызывайте 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.
Note
CallCredentials применяется только в том случае, если канал защищен протоколом TLS. Отправка заголовков проверки подлинности через небезопасное подключение негативно влияет на безопасность и не должна выполняться в рабочих средах. Приложение может задать параметр CallCredentials в настройках канала, чтобы игнорировать это поведение и всегда использовать UnsafeUseInsecureChannelCallCredentials.
Учетные данные в следующем примере настраивают канал так, чтобы токен отправлялся при каждом вызове 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 может создавать клиентов, отправляющих Bearer-токен с помощью 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регистрируется в DI с ограниченным областью видимости сроком существования. - Фабрика клиента 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с DI в скоупированном времени существования.AppTokenProviderкэширует маркер, чтобы его нужно было вычислить только в первом вызове в заданной области. - Регистрирует тип
GreeterClientв фабрике клиента. - Настраивает
AddCallCredentialsдля этого клиента. Делегат исполняется при каждом вызове и добавляет в метаданные токен, полученный отITokenProvider.
Проверка подлинности сертификатов клиента
Клиент может также предоставить сертификат клиента для проверки подлинности.
Проверка подлинности по сертификату происходит на уровне TLS, задолго до его попадания в ASP.NET Core. Когда запрос попадает в ASP.NET Core, пакет проверки подлинности сертификата клиента позволяет обработать сертификат в ClaimsPrincipal.
Note
Сервер должен быть настроен для принятия сертификатов клиентов. Сведения о принятии сертификатов клиента в 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. Пользовательские заголовки можно отправлять с помощью коллекции заголовков опции.
Note
Проверка подлинности 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