Поделиться через


Создание безопасных микрослужб и веб-приложений .NET

Подсказка

Это фрагмент из электронной книги «Архитектура микрослужб .NET для контейнеризованных приложений .NET», доступной в документации .NET или в виде бесплатного скачиваемого PDF-файла, который можно прочитать в автономном режиме.

Архитектура микросервисов .NET для приложений .NET в контейнерах, миниатюра обложки электронной книги.

Существует так много аспектов безопасности в микрослужбах и веб-приложениях, что тема может легко взять несколько книг, таких как этот. Таким образом, в этом разделе мы сосредоточимся на проверке подлинности, авторизации и секретах приложений.

Реализация проверки подлинности в микрослужбах и веб-приложениях .NET

Часто необходимо, чтобы ресурсы и API, опубликованные службой, были ограничены определенными доверенными пользователями или клиентами. Первым шагом к принятию таких решений доверия на уровне API является проверка подлинности. Проверка подлинности — это процесс надежной проверки удостоверения пользователя.

В сценариях микрослужб проверка подлинности обычно обрабатывается централизованно. Если вы используете шлюз API, шлюз является хорошим местом для проверки подлинности, как показано на рис. 9-1. Если вы используете этот подход, убедитесь, что доступ к отдельным микрослужбам напрямую (без шлюза API) невозможен, если только не предусмотрены дополнительные меры безопасности для проверки подлинности сообщений, независимо от того, поступают ли они из шлюза или нет.

Схема взаимодействия клиентского мобильного приложения с серверной частью.

Рис. 9-1. Централизованная проверка подлинности с помощью шлюза API

При централизованной проверке подлинности шлюз API добавляет сведения о пользователях при пересылке запросов в микрослужбы. Если к службам можно получить доступ напрямую, служба проверки подлинности, например Azure Active Directory или выделенная микрослужба проверки подлинности, выступающая в качестве службы маркеров безопасности (STS), может использоваться для проверки подлинности пользователей. Решения о доверии передаются между службами с использованием токенов безопасности или файлов cookie. (Эти маркеры можно совместно использовать между приложениями ASP.NET Core при необходимости, реализуя общий доступ к файлам cookie.) Этот шаблон показан на рисунке 9-2.

Схема проверки подлинности с помощью внутренних микрослужб.

Рис. 9-2. Аутентификация посредством микросервиса идентификации; доверие передается с помощью токена авторизации

Если доступ к микрослужбам осуществляется напрямую, доверие, которое включает проверку подлинности и авторизацию, обрабатывается маркером безопасности, выданным выделенной микрослужбой, совместно используемым микрослужбами.

Аутентификация с помощью ASP.NET Core Identity

Основной механизм в ASP.NET Core для идентификации пользователей приложения — это система членства ASP.NET Core Identity . В ASP.NET Core Identity в хранилище данных, настроенном разработчиком, хранятся сведения о пользователях (включая данные для входа, роли и утверждений). Как правило, хранилище данных ASP.NET Core Identity — это хранилище Entity Framework, предоставленное в пакете Microsoft.AspNetCore.Identity.EntityFrameworkCore . Однако пользовательские хранилища или другие сторонние пакеты можно использовать для хранения сведений об удостоверениях в Azure Table Storage, CosmosDB или других местах.

Подсказка

ASP.NET Core 2.1 и более поздних версий предоставляет ASP.NET Core Identity в качестве библиотеки классов Razor, поэтому в проекте не будет отображаться большой объем необходимого кода, как и в предыдущих версиях. Дополнительные сведения о настройке кода идентификации в соответствии с вашими потребностями см. в разделе "Шаблон удостоверения" в проектах ASP.NET Core.

Следующий код взят из шаблона проекта MVC веб-приложения ASP.NET Core с выбранной проверкой подлинности отдельных учетных записей пользователей. Здесь показано, как настроить ASP.NET Core Identity с помощью Entity Framework Core в файле Program.cs .

//...
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddDefaultIdentity<IdentityUser>(options =>
    options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();

builder.Services.AddRazorPages();
//...

После настройки ASP.NET Core Identity его можно включить, добавив app.UseAuthentication() и endpoints.MapRazorPages(), как показано в следующем коде в файле Program.cs службы.

//...
app.UseRouting();

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

app.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages();
});
//...

Это важно

Строки в приведенном выше коде ДОЛЖНЫ БЫТЬ В УКАЗАННОМ ПОРЯДКЕ для правильной работы Identity.

Использование ASP.NET Core Identity включает несколько сценариев:

  • Создайте сведения о пользователе с помощью типа UserManager (userManager.CreateAsync).

  • Проверка подлинности пользователей с помощью типа SignInManager. Вы можете использовать signInManager.SignInAsync для входа напрямую или signInManager.PasswordSignInAsync для подтверждения правильности пароля пользователя, а затем войти в систему.

  • Определите пользователя на основе сведений, хранящихся в файле cookie (который считывается посредником ASP.NET Core Identity), чтобы последующие запросы из браузера включали удостоверение и запросы пользователя, выполнившего вход.

ASP.NET Core Identity также поддерживает двухфакторную проверку подлинности.

Для сценариев проверки подлинности, использующих локальное хранилище данных пользователя и сохраняющие удостоверение между запросами с помощью файлов cookie (как обычно для веб-приложений MVC), ASP.NET Core Identity — это рекомендуемое решение.

Проверка подлинности с помощью внешних поставщиков

ASP.NET Core также поддерживает использование внешних провайдеров аутентификации, чтобы пользователи могли входить с помощью потоков OAuth 2.0. Это означает, что пользователи могут войти с помощью существующих процессов проверки подлинности от поставщиков, таких как Microsoft, Google, Facebook или Twitter, и связать эти удостоверения с удостоверением ASP.NET Core в приложении.

Чтобы использовать внешнюю проверку подлинности, помимо включения промежуточного слоя проверки подлинности, как упоминалось ранее, методом app.UseAuthentication(), необходимо также зарегистрировать внешний поставщик в Program.cs, как показано в следующем примере:

//...
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

services.AddAuthentication()
    .AddMicrosoftAccount(microsoftOptions =>
    {
        microsoftOptions.ClientId = builder.Configuration["Authentication:Microsoft:ClientId"];
        microsoftOptions.ClientSecret = builder.Configuration["Authentication:Microsoft:ClientSecret"];
    })
    .AddGoogle(googleOptions => { ... })
    .AddTwitter(twitterOptions => { ... })
    .AddFacebook(facebookOptions => { ... });
//...

Популярные внешние поставщики проверки подлинности и связанные пакеты NuGet показаны в следующей таблице:

Поставщик Пакет
Корпорация Майкрософт Microsoft.AspNetCore.Authentication.MicrosoftAccount
Google Microsoft.AspNetCore.Authentication.Google
Facebook Microsoft.AspNetCore.Authentication.Facebook
Твиттер Microsoft.AspNetCore.Authentication.Twitter

Во всех случаях необходимо выполнить процедуру регистрации приложения, зависящую от поставщика и которая обычно включает:

  1. Получение идентификатора клиентского приложения.
  2. Получение секрета клиентского приложения.
  3. Настройка URL-адреса перенаправления, обрабатываемая авторизационным промежуточным ПО и зарегистрированным поставщиком
  4. При желании можно настроить URL-адрес выхода для правильной обработки процесса выхода в сценарии единого входа.

Для получения дополнительной информации о настройке приложения для внешнего поставщика см. раздел о проверке подлинности внешнего поставщика в документации ASP.NET Core.

Подсказка

Все сведения обрабатываются ПО промежуточного слоя авторизации и службами, упомянутыми ранее. Поэтому при создании проекта веб-приложения ASP.NET Core в Visual Studio необходимо выбрать вариант проверки подлинности отдельной учетной записи пользователя , как показано на рисунке 9-3, помимо регистрации поставщиков проверки подлинности, упомянутых ранее.

Снимок экрана: диалоговое окно

Рис. 9-3. Выбор параметра "Отдельные учетные записи пользователей" для использования внешней проверки подлинности при создании проекта веб-приложения в Visual Studio 2019.

Помимо внешних поставщиков проверки подлинности, перечисленных ранее, доступны сторонние пакеты, предоставляющие промежуточное программное обеспечение для работы с ещё большим числом внешних поставщиков проверки подлинности. Список см. в репозитории AspNet.Security.OAuth.Providers на сайте GitHub.

Вы также можете создать собственное внешнее ПО промежуточного слоя проверки подлинности, чтобы решить некоторые особые потребности.

Проверка подлинности с помощью маркеров носителя

Проверка подлинности с помощью ASP.NET Core Identity (или Identity плюс внешних поставщиков проверки подлинности) хорошо подходит для многих сценариев веб-приложения, в которых необходимо хранить сведения о пользователе в файле cookie. Однако в других сценариях файлы cookie не являются естественным средством сохранения и передачи данных.

Например, в веб-API ASP.NET Core, который предоставляет RESTful-конечные точки, к которым могут обращаться одностраничные приложения (SPAs), нативные клиенты или даже другие веб-API, обычно предпочтительнее использовать аутентификацию с использованием токенов. Эти типы приложений не работают с файлами cookie, но могут легко получить маркер носителя и включить его в заголовок авторизации последующих запросов. Чтобы включить аутентификацию токенов, ASP.NET Core поддерживает несколько способов использования OAuth 2.0 и OpenID Connect.

Проверка подлинности с помощью поставщика удостоверений OpenID Connect или OAuth 2.0

Если сведения о пользователе хранятся в Azure Active Directory или другом решении удостоверений, поддерживающем OpenID Connect или OAuth 2.0, можно использовать пакет Microsoft.AspNetCore.Authentication.OpenIdConnect для проверки подлинности с помощью рабочего процесса OpenID Connect. Например, чтобы выполнить проверку подлинности в микрослужбе Identity.Api в eShopOnContainers, веб-приложение ASP.NET Core может использовать ПО промежуточного слоя из этого пакета, как показано в следующем упрощенном примере в Program.cs:

// Program.cs

var identityUrl = builder.Configuration.GetValue<string>("IdentityUrl");
var callBackUrl = builder.Configuration.GetValue<string>("CallBackUrl");
var sessionCookieLifetime = builder.Configuration.GetValue("SessionCookieLifetimeMinutes", 60);

// Add Authentication services

services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddCookie(setup => setup.ExpireTimeSpan = TimeSpan.FromMinutes(sessionCookieLifetime))
.AddOpenIdConnect(options =>
{
    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.Authority = identityUrl.ToString();
    options.SignedOutRedirectUri = callBackUrl.ToString();
    options.ClientId = useLoadTest ? "mvctest" : "mvc";
    options.ClientSecret = "secret";
    options.ResponseType = useLoadTest ? "code id_token token" : "code id_token";
    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = true;
    options.RequireHttpsMetadata = false;
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("orders");
    options.Scope.Add("basket");
    options.Scope.Add("marketing");
    options.Scope.Add("locations");
    options.Scope.Add("webshoppingagg");
    options.Scope.Add("orders.signalrhub");
});

// Build the app
//…
app.UseAuthentication();
//…
app.UseEndpoints(endpoints =>
{
    //...
});

При использовании этого процесса ПО промежуточного слоя ASP.NET Core Identity не требуется, так как всё хранение пользовательской информации и аутентификация обрабатываются службой Identity.

Выдача маркеров безопасности из службы ASP.NET Core

Если вы предпочитаете выдавать маркеры безопасности для локальных пользователей ASP.NET Core Identity, а не с помощью внешнего поставщика удостоверений, вы можете воспользоваться некоторыми хорошими сторонними библиотеками.

IdentityServer4 и OpenIddict — это поставщики OpenID Connect, которые легко интегрируются с ASP.NET Core Identity, что позволяет выдавать маркеры безопасности из службы ASP.NET Core. В документации IdentityServer4 содержатся подробные инструкции по использованию библиотеки. Однако основные шаги по использованию IdentityServer4 для выдачи маркеров приведены ниже.

  1. Вы настраиваете IdentityServer4 в Program.cs путем вызова построителя. Services.AddIdentityServer.

  2. Вы вызываете приложение. UseIdentityServer в Program.cs , чтобы добавить IdentityServer4 в конвейер обработки HTTP-запросов приложения. Это позволяет библиотеке обслуживать запросы к конечным точкам OpenID Connect и OAuth2, таким как /connect/token.

  3. Настройте сервер удостоверений, задав следующие данные:

    • Учетные данные, используемые для подписывания.

    • Ресурсы удостоверений и API, к которым пользователи могут запрашивать доступ:

      • Ресурсы API представляют защищенные данные или функциональные возможности, к которым пользователь может получить доступ с помощью маркера доступа. Примером ресурса API будет веб-API (или набор API), требующим авторизации.

      • Идентификационные ресурсы представляют сведения (заявления), предоставленные клиенту для идентификации пользователя. Утверждения могут содержать имя пользователя, адрес электронной почты и т. д.

    • Клиенты, которые будут подключаться для запроса токенов.

    • Механизм хранения сведений о пользователе, например ASP.NET Core Identity или альтернативный вариант.

При указании клиентов и ресурсов для использования IdentityServer4, вы можете передать IEnumerable<T> коллекцию соответствующего типа в методы, использующие хранилища клиентов или ресурсов в памяти. Кроме того, для более сложных сценариев можно предоставить типы клиентов или поставщиков ресурсов с помощью внедрения зависимостей.

Пример конфигурации для IdentityServer4 для использования ресурсов и клиентов в оперативной памяти, предоставляемых типом IClientStore, созданным пользователем, может выглядеть следующим образом:

// Program.cs

builder.Services.AddSingleton<IClientStore, CustomClientStore>();
builder.Services.AddIdentityServer()
    .AddSigningCredential("CN=sts")
    .AddInMemoryApiResources(MyApiResourceProvider.GetAllResources())
    .AddAspNetIdentity<ApplicationUser>();
//...

Потребление маркеров безопасности

Проверка подлинности в конечной точке OpenID Connect или выдача собственных маркеров безопасности охватывает некоторые сценарии. Но как насчет службы, которая просто должна ограничить доступ к тем пользователям, у которых есть допустимые маркеры безопасности, предоставляемые другой службой?

Для этого сценария в пакете Microsoft.AspNetCore.Authentication.JwtBearer доступен промежуточный слой аутентификации, который обрабатывает токены JWT. JWT обозначает "веб-токен JSON" и является общим форматом маркера безопасности (определяемым RFC 7519) для обмена утверждениями безопасности. Упрощенный пример использования промежуточного слоя для потребления этих токенов может выглядеть как этот фрагмент кода, взятый из микросервиса Ordering.Api в eShopOnContainers.

// Program.cs

var identityUrl = builder.Configuration.GetValue<string>("IdentityUrl");

// Add Authentication services

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme;

}).AddJwtBearer(options =>
{
    options.Authority = identityUrl;
    options.RequireHttpsMetadata = false;
    options.Audience = "orders";
});

// Build the app

app.UseAuthentication();
//…
app.UseEndpoints(endpoints =>
{
    //...
});

Параметры в этом использовании:

  • Audience представляет приемник входящего маркера или ресурс, которому маркер предоставляет доступ. Если значение, указанное в этом параметре, не соответствует параметру в маркере, маркер будет отклонен.

  • Authority — это адрес сервера аутентификации, выдающего токены. Промежуточное ПО аутентификации JWT использует этот URI для получения открытого ключа, который можно использовать для проверки подписи токена. Промежуточное программное обеспечение также подтверждает, что параметр iss в маркере соответствует этому URI.

Другой параметр, полезен для тестирования. Этот параметр RequireHttpsMetadataимеет значение false, чтобы можно было протестировать в средах, где у вас нет сертификатов. В реальных развертываниях маркеры носителя JWT всегда должны передаваться только по протоколу HTTPS.

С помощью этого посредника токены JWT автоматически извлекаются из заголовков авторизации. Затем они десериализуются, проверяются (с использованием значений в параметрах Audience и Authority), и сохраняются как информация о пользователе, на которую затем могут ссылаться действия MVC или фильтры авторизации.

Промежуточное ПО аутентификации с поддержкой удостоверений JWT также может поддерживать более сложные сценарии, такие как использование локального сертификата для проверки токена, если удостоверяющий орган недоступен. В этом сценарии можно указать TokenValidationParameters объект в объекте JwtBearerOptions .

Дополнительные ресурсы