Как использовать Identity для защиты серверной части веб-API для SPA
Примечание.
Это не последняя версия этой статьи. В текущем выпуске смотрите версию статьи для .NET 9.
Предупреждение
Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущем выпуске смотрите версию статьи для .NET 9.
Внимание
Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
В текущем выпуске смотрите версию статьи для .NET 9.
ASP.NET Core Identity предоставляет API-интерфейсы, которые обрабатывают проверку подлинности, авторизацию и управление удостоверениями. API позволяют защитить конечные точки серверной части веб-API с помощью проверки подлинности на основе cookie. Вариант на основе токенов доступен для клиентов, которые не могут использовать куки, но при его использовании вы несете ответственность за обеспечение их безопасности. Мы рекомендуем использовать файлы cookie для приложений на основе браузера, так как по умолчанию браузер автоматически обрабатывает их без предоставления им доступа к JavaScript.
В этой статье показано, как с помощью Identity защитить серверную часть веб-API для SPA, таких как приложения на Angular, React и Vue. Те же интерфейсы API серверной части можно использовать для защиты Blazor WebAssembly приложений.
Предварительные требования
Действия, описанные в этой статье, добавляют проверку подлинности и авторизацию в приложение ASP.NET Core Web API, которое:
- Не настроено для проверки подлинности.
- Целевые версии
net8.0
или более поздние. - Может быть минимальным API или API на основе контроллера.
Некоторые инструкции по тестированию в этой статье используют пользовательский интерфейс Swagger, включенный в шаблон проекта. Пользовательский интерфейс Swagger не обязателен для использования с серверной частью веб-API Identity.
Установка пакетов Nuget
Установите следующие пакеты NuGet:
-
Microsoft.AspNetCore.Identity.EntityFrameworkCore
— позволяет Identity работать с Entity Framework Core (EF Core). - Тот, который позволяет EF Core работать с базой данных, например одним из следующих пакетов:
Чтобы быстро приступить к работе, используйте базу данных в памяти.
Измените базу данных позже на SQLite или SQL Server, чтобы сохранить данные пользователей между сеансами при тестировании или использовании в рабочей среде. Это приводит к некоторой сложности по сравнению с операциями в памяти, так как требуется, чтобы база данных была создана с помощью миграций, как показано в руководстве поEF Core началу работы.
Установите эти пакеты с помощью диспетчера пакетов NuGet в Visual Studio или команды dotnet add package CLI.
Создайте IdentityDbContext
.
Добавление класса с именем ApplicationDbContext
, наследуемого от IdentityDbContext<TUser>:
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
public class ApplicationDbContext : IdentityDbContext<IdentityUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) :
base(options)
{ }
}
Показанный код предоставляет специальный конструктор, позволяющий настроить базу данных для разных сред.
При добавлении кода, указанного в этих шагах, добавьте одну или несколько следующих директив using
.
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
Настройка контекста EF Core
Как отмечалось ранее, самый простой способ начать работу — использовать базу данных в памяти. При использовании памяти каждый запуск начинается с новой базы данных, и нет необходимости использовать миграции. После вызова WebApplication.CreateBuilder(args)
добавьте следующий код, чтобы настроить Identity использование базы данных в памяти:
builder.Services.AddDbContext<ApplicationDbContext>(
options => options.UseInMemoryDatabase("AppDb"));
Чтобы сохранить данные пользователей между сеансами при тестировании или использовании в рабочей среде, измените базу данных позже на SQLite или SQL Server.
Добавьте Identity сервисы в контейнер
После вызова WebApplication.CreateBuilder(args)
, вызовите функцию AddAuthorization, чтобы добавить службы в контейнер внедрения зависимостей (DI):
builder.Services.AddAuthorization();
Активируйте Identity API
После вызова WebApplication.CreateBuilder(args)
вызовите AddIdentityApiEndpoints<TUser>(IServiceCollection) и AddEntityFrameworkStores<TContext>(IdentityBuilder).
builder.Services.AddIdentityApiEndpoints<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
По умолчанию активируются как файлы cookie, так и проприетарные токены. Файлы cookie и маркеры выдаются при входе, если в конечной точке входа параметр строки запроса useCookies
является true
.
Нанести на карту маршруты Identity
После вызова builder.Build()
вызовите MapIdentityApi<TUser>(IEndpointRouteBuilder) для сопоставления конечных точек Identity:
app.MapIdentityApi<IdentityUser>();
Защита выбранных конечных точек
Чтобы защитить конечную точку, используйте RequireAuthorization метод расширения для Map{Method}
вызова, определяющего маршрут. Например:
app.MapGet("/weatherforecast", (HttpContext httpContext) =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = summaries[Random.Shared.Next(summaries.Length)]
})
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi()
.RequireAuthorization();
Метод RequireAuthorization
также можно использовать для:
Защита конечных точек пользовательского интерфейса Swagger, как показано в следующем примере:
app.MapSwagger().RequireAuthorization();
Закрепление с помощью определенного требования или разрешения, как показано в следующем примере:
.RequireAuthorization("Admin");
В проекте веб-API на основе контроллера защита конечных точек путем применения атрибута [Authorize
] к контроллеру или действию.
Проверка API
Быстрый способ проверки подлинности — использовать базу данных в памяти и пользовательский интерфейс Swagger, включенный в шаблон проекта. Ниже показано, как протестировать API с помощью пользовательского интерфейса Swagger. Убедитесь, что конечные точки пользовательского интерфейса Swagger не защищены.
Попытка доступа к защищенной конечной точке
- Запустите приложение и перейдите к пользовательскому интерфейсу Swagger.
- Разверните безопасную конечную точку, например
/weatherforecast
в проекте, созданном шаблоном веб-API. - Выберите Опробовать.
- Выберите Выполнить. Ответ имеет значение
401 - not authorized
.
Тест регистрации
Разверните
/register
и выберите "Попробовать".В разделе "Параметры" пользовательского интерфейса показан пример текста запроса:
{ "email": "string", "password": "string" }
Замените "string" допустимым адресом электронной почты и паролем, а затем нажмите кнопку "Выполнить".
Чтобы соответствовать правилам проверки паролей по умолчанию, пароль должен иметь по крайней мере шесть символов и содержать по крайней мере один из следующих символов:
- Буква в верхнем регистре
- Буква в нижнем регистре
- Цифра
- неалфавитно-цифровой символ
Если ввести недопустимый адрес электронной почты или неправильный пароль, результат содержит ошибки проверки. Ниже приведен пример текста ответа с ошибками проверки:
{ "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", "title": "One or more validation errors occurred.", "status": 400, "errors": { "PasswordTooShort": [ "Passwords must be at least 6 characters." ], "PasswordRequiresNonAlphanumeric": [ "Passwords must have at least one non alphanumeric character." ], "PasswordRequiresDigit": [ "Passwords must have at least one digit ('0'-'9')." ], "PasswordRequiresLower": [ "Passwords must have at least one lowercase ('a'-'z')." ] } }
Ошибки возвращаются в формате ProblemDetails , чтобы клиент смог проанализировать их и отобразить ошибки проверки по мере необходимости.
Успешная регистрация приводит к ответу
200 - OK
.
Проверка имени входа
Разверните
/login
, затем выберите Попробовать. В тексте запроса примера показаны два дополнительных параметра:{ "email": "string", "password": "string", "twoFactorCode": "string", "twoFactorRecoveryCode": "string" }
Дополнительные свойства JSON не требуются для этого примера и могут быть удалены. Задайте для параметра
useCookies
значениеtrue
.Замените "string" адресом электронной почты и паролем, используемым для регистрации, а затем нажмите кнопку "Выполнить".
Успешный вход приводит к ответу
200 - OK
с cookie в заголовке ответа.
Повторное тестирование защищенной конечной точки
После успешного входа повторно запустите безопасную конечную точку. Проверка подлинности cookie автоматически отправляется с запросом, и конечная точка авторизована. Cookie-основанная проверка подлинности безопасно встроена в браузер и "просто работает".
Тестирование с помощью клиентов, которые не являются браузерами
Некоторые веб-клиенты могут не включать файлы cookie в заголовок по умолчанию:
Если вы используете средство для тестирования API, может потребоваться включить файлы cookie в параметрах.
API JavaScript
fetch
по умолчанию не включает файлы cookie. Включите их, установивcredentials
на значениеinclude
в настройках.Запущенный
HttpClient
в приложении Blazor WebAssembly нужно, чтобыHttpRequestMessage
включал учетные данные, например, как показано в следующем примере:request.SetBrowserRequestCredential(BrowserRequestCredentials.Include);
Использование проверки подлинности на основе токенов
Мы рекомендуем использовать файлы cookie в приложениях на основе браузера, так как по умолчанию браузер автоматически обрабатывает их без предоставления им доступа к JavaScript.
Выдается собственный для платформы ASP.NET Core токен, который можно использовать для аутентификации последующих запросов. Токен передается в заголовке Authorization
в качестве токена носителя. Также выдается токен обновления. Этот маркер позволяет приложению запрашивать новый маркер, когда срок действия старого маркера истекает без повторного входа пользователя.
Маркеры не являются стандартными JSON Web Tokens (JWTs). Использование пользовательских значков намеренно, так как встроенный Identity API в основном предназначен для простых сценариев. Параметр токена не предназначен для полноценного поставщика услуг идентификации или сервера токенов, а вместо этого служит альтернативой варианту cookie для клиентов, которые не могут использовать куки.
Чтобы использовать проверку подлинности на основе маркеров, установите параметр строки запроса useCookies
в false
при вызове конечной точки /login
. Маркеры используют схему проверки подлинности носителя . С помощью токена, возвращаемого из вызова /login
, последующие вызовы защищенных конечных точек должны добавить заголовок Authorization: Bearer <token>
, где <token>
является токеном доступа. Дополнительные сведения см. в разделе "Использование конечной POST /login
точки " далее в этой статье.
Выход
Чтобы предоставить пользователю способ выхода из системы, определите конечную /logout
точку, как показано в следующем примере:
app.MapPost("/logout", async (SignInManager<IdentityUser> signInManager,
[FromBody] object empty) =>
{
if (empty != null)
{
await signInManager.SignOutAsync();
return Results.Ok();
}
return Results.Unauthorized();
})
.WithOpenApi()
.RequireAuthorization();
Укажите пустой объект JSON ({}
) в тексте запроса при вызове этой конечной точки. Следующий код является примером вызова конечной точки выхода:
public signOut() {
return this.http.post('/logout', {}, {
withCredentials: true,
observe: 'response',
responseType: 'text'
Конечные MapIdentityApi<TUser>
точки
Вызов MapIdentityApi<TUser>
добавляет в приложение следующие конечные точки:
POST /register
POST /login
POST /refresh
GET /confirmEmail
POST /resendConfirmationEmail
POST /forgotPassword
POST /resetPassword
POST /manage/2fa
GET /manage/info
POST /manage/info
Используйте конечную точку POST /register
Текст запроса должен иметь Email и Password свойства:
{
"email": "string",
"password": "string",
}
Дополнительные сведения см. в разделе:
- Тестовая регистрация упоминается ранее в этой статье.
- RegisterRequest.
Используйте конечную точку POST /login
В теле запроса Email и Password обязательны. Если включена двухфакторная проверка подлинности (2FA), требуется либо TwoFactorCode, либо TwoFactorRecoveryCode. Если 2FA не включена, опустите оба twoFactorCode
и twoFactorRecoveryCode
. Дополнительные сведения см. в разделе "Использование конечной POST /manage/2fa
точки " далее в этой статье.
Вот пример тела запроса с не включенной двухфакторной аутентификацией (2FA):
{
"email": "string",
"password": "string"
}
Ниже приведены примеры текста запроса с включенным 2FA:
-
{ "email": "string", "password": "string", "twoFactorCode": "string", }
-
{ "email": "string", "password": "string", "twoFactorRecoveryCode": "string" }
Конечная точка ожидает параметр строки запроса:
-
useCookies
— Установите значениеtrue
для аутентификации на основе cookie. Установитеfalse
или пропустите для аутентификации на основе токенов.
Для получения дополнительной информации об аутентификации на основе cookie, см. раздел "Тест входа" ранее в этой статье.
Проверка подлинности на основе токенов
Если useCookies
это false
или опущено, аутентификация на основе токенов включена. Текст ответа содержит следующие свойства:
{
"tokenType": "string",
"accessToken": "string",
"expiresIn": 0,
"refreshToken": "string"
}
Дополнительные сведения об этих свойствах см. в разделе AccessTokenResponse.
Поместите маркер доступа в заголовок, чтобы выполнить прошедшие проверку подлинности запросы, как показано в следующем примере.
Authorization: Bearer {access token}
Когда срок действия маркера доступа вот-вот истечет, вызовите конечный узел /refresh.
Используйте конечную точку POST /refresh
Для использования только с проверкой подлинности на основе токенов. Получает новый токен доступа, не заставляя пользователя снова входить в систему. Вызовите эту конечную точку, когда срок действия токена доступа вот-вот истечет.
Тело запроса содержит только RefreshToken. Ниже приведен пример текста запроса:
{
"refreshToken": "string"
}
Если вызов выполнен успешно, текст ответа является новым AccessTokenResponse, как показано в следующем примере:
{
"tokenType": "string",
"accessToken": "string",
"expiresIn": 0,
"refreshToken": "string"
}
Используйте конечную точку GET /confirmEmail
Если Identity настроено для подтверждения по электронной почте, успешный вызов конечной точки /register
отправляет электронное письмо, содержащее ссылку на конечную точку /confirmEmail
. Ссылка содержит следующие параметры строки запроса:
userId
code
-
changedEmail
— включается только в том случае, если пользователь изменил адрес электронной почты во время регистрации.
Identity предоставляет текст по умолчанию для сообщения электронной почты подтверждения. По умолчанию тема электронной почты — "Подтверждение электронной почты", а текст электронной почты выглядит следующим образом:
Please confirm your account by <a href='https://contoso.com/confirmEmail?userId={user ID}&code={generated code}&changedEmail={new email address}'>clicking here</a>.
RequireConfirmedEmail Если для свойства задано true
значение, пользователь не сможет войти, пока адрес электронной почты не будет подтвержден, щелкнув ссылку в сообщении электронной почты. Конечная /confirmEmail
точка:
- Подтверждает адрес электронной почты и позволяет пользователю войти в систему.
- Возвращает текст "Спасибо за подтверждение вашей электронной почты" в теле ответа.
Чтобы настроить Identity для подтверждения электронной почты, добавьте код в Program.cs
, чтобы установить RequireConfirmedEmail
на true
, и добавьте класс, который реализует IEmailSender в DI-контейнер. Например:
builder.Services.Configure<IdentityOptions>(options =>
{
options.SignIn.RequireConfirmedEmail = true;
});
builder.Services.AddTransient<IEmailSender, EmailSender>();
Дополнительные сведения см. в разделе "Подтверждение учетной записи" и восстановление паролей в ASP.NET Core.
Identity предоставляет текст по умолчанию для других сообщений электронной почты, которые необходимо отправить, например, для двухфакторной аутентификации и сброса пароля. Чтобы настроить эти сообщения электронной почты, предоставьте пользовательскую реализацию IEmailSender
интерфейса. В предыдущем примере — это класс, EmailSender
реализующий IEmailSender
. Дополнительные сведения, включая пример класса, реализующего IEmailSender
, см. в разделе "Подтверждение учетной записи" и восстановление паролей в ASP.NET Core.
Используйте конечную точку POST /resendConfirmationEmail
Отправляет сообщение электронной почты только в том случае, если адрес действителен для зарегистрированного пользователя.
Тело запроса содержит только Email. Ниже приведен пример текста запроса:
{
"email": "string"
}
Дополнительные сведения см. в разделе "Использование конечной GET /confirmEmail
точки " ранее в этой статье.
Используйте конечную точку POST /forgotPassword
Создает сообщение электронной почты, содержащее код сброса пароля. Отправьте этот код на /resetPassword
вместе с новым паролем.
Тело запроса содержит только Email. Приведем пример:
{
"email": "string"
}
Сведения о том, как включить Identity отправку сообщений электронной почты, см. в разделе "Использование конечной GET /confirmEmail
точки".
Используйте конечную точку POST /resetPassword
Вызовите эту конечную точку после получения кода сброса, вызвав конечную точку /forgotPassword
.
Для текста запроса требуется Email, ResetCodeи NewPassword. Приведем пример:
{
"email": "string",
"resetCode": "string",
"newPassword": "string"
}
Используйте конечную точку POST /manage/2fa
Настраивает двухфакторную проверку подлинности (2FA) для пользователя. Если включена 2FA, для успешного входа требуется код, созданный приложением authenticator, в дополнение к адресу электронной почты и паролю.
Включить 2FA
Чтобы включить 2FA для текущего пользователя, прошедшего проверку подлинности, выполните следующие действия.
Вызовите конечную точку
/manage/2fa
, отправив пустой объект JSON ({}
) в тексте запроса.Тело ответа содержит SharedKey вместе с рядом других свойств, которые не требуются на данный момент. Общий ключ используется для настройки приложения authenticator. Пример содержимого ответа:
{ "sharedKey": "string", "recoveryCodesLeft": 0, "recoveryCodes": null, "isTwoFactorEnabled": false, "isMachineRemembered": false }
Используйте общий ключ для получения одноразового пароля (TOTP) с временной основой. Дополнительные сведения см. в разделе "Включение создания QR-кода" для приложений проверки подлинности TOTP в ASP.NET Core.
Вызовите конечную точку
/manage/2fa
, отправив в теле запроса TOTP и"enable": true
. Например:{ "enable": true, "twoFactorCode": "string" }
Текст ответа подтверждает, что IsTwoFactorEnabled имеет значение true и предоставляет RecoveryCodes. Коды восстановления используются для входа, если приложение для аутентификации недоступно. Пример текста ответа после успешного включения 2FA:
{ "sharedKey": "string", "recoveryCodesLeft": 10, "recoveryCodes": [ "string", "string", "string", "string", "string", "string", "string", "string", "string", "string" ], "isTwoFactorEnabled": true, "isMachineRemembered": false }
Вход с помощью 2FA
Вызовите конечную точку /login
, отправив адрес электронной почты, пароль и TOTP в тексте запроса. Например:
{
"email": "string",
"password": "string",
"twoFactorCode": "string"
}
Если у пользователя нет доступа к приложению аутентификатор, войдите в систему, вызвав /login
эндпоинт с одним из кодов восстановления, предоставленных при включении 2FA. Текст запроса будет выглядеть как в следующем примере.
{
"email": "string",
"password": "string",
"twoFactorRecoveryCode": "string"
}
Сброс кодов восстановления
Чтобы получить новый набор кодов восстановления, вызовите эту конечную точку с ResetRecoveryCodes заданным значением true
. Ниже приведен пример текста запроса:
{
"resetRecoveryCodes": true
}
Сброс общего ключа
Чтобы получить новый случайный общий ключ, вызовите эту конечную точку с ResetSharedKey заданным значением true
. Ниже приведен пример текста запроса:
{
"resetSharedKey": true
}
Сброс ключа автоматически отключает требование двухфакторной аутентификации для аутентифицированного пользователя до тех пор, пока оно не будет снова включено более поздним запросом.
Забыли компьютер
Чтобы очистить cookie флаг "запомнить меня" при его наличии, вызовите эту конечную точку, установив значение параметра ForgetMachine в true. Ниже приведен пример текста запроса:
{
"forgetMachine": true
}
Эта конечная точка не влияет на проверку подлинности на основе маркеров.
Используйте конечную точку GET /manage/info
Получает адрес электронной почты и состояние подтверждения электронной почты пользователя, вошедшего в систему. Данные были исключены из этого сервиса по соображениям безопасности. Если требуются утверждения, используйте интерфейсы API на стороне сервера, чтобы настроить конечную точку для утверждений. Или вместо предоставления общего доступа ко всем утверждениям пользователей предоставьте конечную точку проверки, которая принимает утверждение и отвечает, имеет ли пользователь его.
Запрос не требует каких-либо параметров. Тело ответа содержит свойства Email и IsEmailConfirmed, как показано в следующем примере:
{
"email": "string",
"isEmailConfirmed": true
}
Используйте конечную точку POST /manage/info
Обновляет адрес электронной почты и пароль пользователя, вошедшего в систему. Отправьте NewEmail, NewPassword и OldPassword в теле запроса, как показано в следующем примере.
{
"newEmail": "string",
"newPassword": "string",
"oldPassword": "string"
}
Вот пример текста ответа:
{
"email": "string",
"isEmailConfirmed": false
}
См. также
Дополнительные сведения см. на следующих ресурсах:
- Выберите решение для управления удостоверениями
- Identity решения по управлению веб-приложениями .NET
- Простая авторизация в ASP.NET Core
- Добавление, скачивание и удаление пользовательских данных Identity в проект ASP.NET Core
- Создание приложения ASP.NET Core с защитой данных пользователя с помощью авторизации
- Подтверждение учетной записи и восстановление пароля в ASP.NET Core
- Включение создания QR-кодов для приложений проверки подлинности TOTP в ASP.NET Core
-
Пример серверной части веб-API для SPAs Http-файл показывает проверку подлинности на основе токенов. Например:
- Не задано
useCookies
- Использует заголовок авторизации для передачи токена
- Показывает обновление для расширения сеанса без повторного входа пользователя
- Не задано
- Пример приложения Angular, которое используется Identity для защиты серверной части веб-API
Шаблоны ASP.NET Core предлагают проверку подлинности в одностраничных приложениях (SPAs), используя поддержку авторизации API. ASP.NET Core Identity для проверки подлинности и хранения пользователей объединяется с Duende Identity Server для реализации OpenID Connect.
Внимание
Компания Duende Software может потребовать лицензионный сбор за использование Duende IdentityServer в промышленной эксплуатации. Дополнительные сведения см. в статье Миграция с ASP.NET Core 5.0 на 6.0.
Параметр проверки подлинности был добавлен в шаблоны проектов Angular и React , аналогичные параметру проверки подлинности в шаблонах проектов веб-приложения (Model-View-Controller) (MVC) и веб-приложения (Razor Pages). Допустимые значения параметров — None и Individual. Шаблон проекта React.js и Redux не поддерживает параметр аутентификации на данный момент.
Создание приложения с поддержкой авторизации API
Аутентификацию пользователей и авторизацию можно использовать как с Angular, так и с React SPA. Откройте окно командной оболочки и выполните следующую команду:
Angular:
dotnet new angular -au Individual
React:
dotnet new react -au Individual
Предыдущая команда создает приложение ASP.NET Core с каталогом ClientApp , содержащим SPA.
Общее описание основных компонентов приложения ASP.NET
В следующих разделах описываются дополнения к проекту при включенной поддержке проверки подлинности:
Program.cs
В следующих примерах кода используется пакет NuGet Microsoft.AspNetCore.ApiAuthorization.IdentityServer . Примеры настраивают проверку подлинности и авторизации API с использованием методов расширения AddApiAuthorization и AddIdentityServerJwt. Проекты, использующие шаблоны проектов React или Angular SPA с проверкой подлинности, включают ссылку на этот пакет.
dotnet new angular -au Individual
создает следующий Program.cs
файл:
using Microsoft.AspNetCore.Authentication;
using Microsoft.EntityFrameworkCore;
using output_directory_name.Data;
using output_directory_name.Models;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
builder.Services.AddAuthentication()
.AddIdentityServerJwt();
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseIdentityServer();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
app.MapRazorPages();
app.MapFallbackToFile("index.html");
app.Run();
Предыдущий код настраивает:
Identity с пользовательским интерфейсом по умолчанию:
builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlite(connectionString)); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<ApplicationDbContext>();
IdentityServer с дополнительным
AddApiAuthorization
вспомогательным методом, который настраивает некоторые стандартные соглашения ASP.NET Core вдобавок к IdentityServer.builder.Services.AddIdentityServer() .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
Проверка подлинности с помощью дополнительного вспомогательного метода
AddIdentityServerJwt
, который настраивает приложение для проверки маркеров JWT, созданных IdentityServer:builder.Services.AddAuthentication() .AddIdentityServerJwt();
Промежуточное программное обеспечение аутентификации, которое отвечает за проверку учетных данных запроса, а также установку пользователя в контексте запроса:
app.UseAuthentication();
Промежуточное ПО IdentityServer, которое предоставляет конечные точки OpenID Connect:
app.UseIdentityServer();
Предупреждение
В этой статье показано использование строк подключения. С локальной базой данных пользователю не нужно проходить проверку подлинности, но в production-среде строка подключения иногда включает пароль для проверки подлинности. Учетные данные владельца ресурса (ROPC) — это риск безопасности, который следует избежать в рабочих базах данных. Рабочие приложения должны использовать самый безопасный поток проверки подлинности. Дополнительные сведения о проверке подлинности для приложений, развернутых в тестовых или рабочих средах, см. в разделе "Безопасные потоки проверки подлинности".
Служба приложений Azure в Linux
Для развертывания службы приложений Azure на Linux укажите издателя явно.
builder.Services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
options.Authority = "{AUTHORITY}";
});
В предыдущем коде заполнитель {AUTHORITY}
служит Authority для использования при вызовах OpenID Connect.
Пример:
options.Authority = "https://contoso-service.azurewebsites.net";
AddApiAuthorization
Этот вспомогательный метод настраивает IdentityServer для использования поддерживаемой конфигурации. IdentityServer — это функциональная и расширяемая платформа для устранения проблем с безопасностью приложений. В то же время это обеспечивает ненужную сложность для наиболее распространенных сценариев. Следовательно, вам предоставляется набор соглашений и параметров конфигурации, которые считаются хорошей отправной точкой. После изменения проверки подлинности полная мощность IdentityServer по-прежнему доступна для настройки проверки подлинности в соответствии с вашими потребностями.
AddIdentityServerJwt
Этот вспомогательный метод настраивает схему политики для приложения в качестве обработчика проверки подлинности по умолчанию. Политика настроена, чтобы разрешить Identity обрабатывать все запросы, перенаправленные в любой Identity подпуть в пространстве URL-адресов "/Identity".
JwtBearerHandler
обрабатывает все остальные запросы. Кроме того, этот метод регистрирует <<ApplicationName>>API
ресурс API в IdentityServer с областью <<ApplicationName>>API
по умолчанию и настраивает промежуточное ПО JWT Bearer для проверки токенов, выданных IdentityServer для приложения.
WeatherForecastController
В файле обратите внимание на атрибут, [Authorize]
примененный к классу, который указывает, что пользователю необходимо авторизоваться на основе политики по умолчанию для доступа к ресурсу. Политика авторизации по умолчанию настраивается для использования стандартной схемы проверки подлинности, которая устанавливается с помощью AddIdentityServerJwt
в схему политики, указанную выше, делая тем самым JwtBearerHandler
, сконфигурированным таким вспомогательным методом, обработчиком по умолчанию для запросов к приложению.
ApplicationDbContext
Обратите внимание, что в файле используется тот же самый DbContext
, что и в Identity, за исключением того, что он расширяет ApiAuthorizationDbContext
(более производный класс от IdentityDbContext
), чтобы включить схему для IdentityServer.
Чтобы получить полный контроль над схемой базы данных, наследуйте от одного из доступных IdentityDbContext
классов и настройте контекст для включения схемы Identity путем вызова метода builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value)
OnModelCreating
.
OidcConfigurationController
В файле обратите внимание на конечную точку, подготовленную для обслуживания параметров OIDC, которые клиент должен использовать.
appsettings.json
appsettings.json
В файле корневого каталога проекта есть новый IdentityServer
раздел, описывающий список настроенных клиентов. В следующем примере есть один клиент. Имя клиента соответствует имени приложения и сопоставляется по соглашению с параметром ClientId
OAuth. Профиль указывает на настраиваемый тип приложения. Он используется внутри системы для управления соглашениями, упрощающими процесс настройки сервера. Существует несколько профилей, как описано в разделе "Профили приложений".
"IdentityServer": {
"Clients": {
"angularindividualpreview3final": {
"Profile": "IdentityServerSPA"
}
}
}
appsettings.Development.json
В файле корневого каталога проекта appsettings.Development.json
есть раздел IdentityServer
, который описывает ключ, используемый для подписания токенов. При развертывании в рабочей среде необходимо подготовить и развернуть ключ вместе с приложением, как описано в разделе "Развертывание в рабочей среде ".
"IdentityServer": {
"Key": {
"Type": "Development"
}
}
Общее описание приложения Angular
Поддержка проверки подлинности и авторизации API в шаблоне Angular находится в собственном модуле Angular в каталоге ClientApp/src/api-authorization . Модуль состоит из следующих элементов:
- 3 компонента:
-
login.component.ts
: обрабатывает поток входа приложения. -
logout.component.ts
: обрабатывает процесс выхода из приложения. -
login-menu.component.ts
: мини-приложение, отображающее один из следующих наборов ссылок:- Управление профилем пользователя и ссылки для выхода при аутентификации.
- Регистрация и вход по ссылкам, когда пользователь не проходит проверку подлинности.
-
- Защита
AuthorizeGuard
маршрута, которая может быть добавлена в маршруты и требует, чтобы пользователь прошел проверку подлинности перед посещением маршрута. - Перехватчик
AuthorizeInterceptor
HTTP, который присоединяет маркер доступа к исходящим HTTP-запросам, предназначенным для API, когда пользователь аутентифицирован. - Служба
AuthorizeService
, которая обрабатывает детали процесса аутентификации на более низком уровне и предоставляет информацию о пользователе, прошедшем проверку подлинности, для использования остальной частью приложения. - Модуль Angular, определяющий маршруты, связанные с частями проверки подлинности приложения. Он предоставляет компонент меню входа, перехватчик, защиту и сервис для использования остальной частью приложения.
Общее описание приложения React
Поддержка проверки подлинности и авторизации API в шаблоне React находится в каталоге ClientApp/src/components/api-authorization . Он состоит из следующих элементов:
- 4 компонента:
-
Login.js
: обрабатывает поток входа приложения. -
Logout.js
: обрабатывает процесс выхода из приложения. -
LoginMenu.js
: мини-приложение, отображающее один из следующих наборов ссылок:- Управление профилем пользователя и ссылки для выхода при аутентификации.
- Регистрация и вход по ссылкам, когда пользователь не проходит проверку подлинности.
-
AuthorizeRoute.js
: компонент маршрута, требующий проверки подлинности пользователя перед отрисовкой компонента, указанного в параметреComponent
.
-
- Экспортированный экземпляр
authService
классаAuthorizeService
, который обрабатывает более низкоуровневые детали процесса аутентификации и предоставляет информацию о прошедшем аутентификацию пользователе для использования остальной частью приложения.
Теперь, когда вы видели основные компоненты решения, вы можете более подробно ознакомиться с отдельными сценариями для приложения.
Требовать авторизацию в новом API
По умолчанию система настроена для упрощения авторизации для новых API. Для этого создайте новый контроллер и добавьте [Authorize]
атрибут в класс контроллера или в любое действие в контроллере.
Настройка обработчика проверки подлинности API
Чтобы изменить параметры конфигурации обработчика JWT API, настройте его JwtBearerOptions экземпляр:
builder.Services.AddAuthentication()
.AddIdentityServerJwt();
builder.Services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
...
});
Обработчик JWT API вызывает события, позволяющие управлять процессом проверки подлинности с помощью JwtBearerEvents
. Чтобы обеспечить поддержку авторизации API, AddIdentityServerJwt
регистрирует собственные обработчики событий.
Чтобы настроить обработку события, оберните существующий обработчик событий дополнительной логикой, если это необходимо. Например:
builder.Services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
var onTokenValidated = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
await onTokenValidated(context);
...
}
});
В приведенном выше коде обработчик событий OnTokenValidated
заменён собственной реализацией. Эта реализация:
- Вызывает исходную реализацию, предоставляемую поддержкой авторизации API.
- Запуск собственной пользовательской логики.
Защита клиентской маршрутизации (Angular)
Защита клиентского маршрута выполняется путем добавления авторизации защиты в список гарантий, выполняемых при настройке маршрута. В качестве примера можно увидеть, как маршрут fetch-data
конфигурирован в модуле Angular главного приложения.
RouterModule.forRoot([
// ...
{ path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthorizeGuard] },
])
Важно отметить, что защита маршрута не защищает саму конечную точку (которая по-прежнему требует применения к ней атрибута [Authorize]
), а только запрещает пользователю переходить к заданному клиентскому маршруту, если пользователь не проходит проверку подлинности.
Проверка подлинности запросов API (Angular)
Проверка подлинности запросов к API, размещенным вместе с приложением, выполняется автоматически с помощью перехватчика HTTP-клиента, определенного приложением.
Защита клиентской маршрутизации (React)
Защита клиентского маршрута с помощью AuthorizeRoute
компонента вместо обычного Route
компонента. Например, обратите внимание, как fetch-data
маршрут настроен в компоненте App
:
<AuthorizeRoute path='/fetch-data' component={FetchData} />
Защита маршрута:
- Не защищает фактическую конечную точку (которая по-прежнему требует применения атрибута
[Authorize]
к нему). - Только не позволяет пользователю перейти на указанный маршрут клиентской стороны, если не выполнена аутентификация.
Проверка подлинности запросов API (React)
Проверка подлинности запросов с помощью React выполняется путем импорта экземпляра authService
из .AuthorizeService
Маркер доступа извлекается из authService
и добавляется к запросу, как показано ниже. В компонентах React эта работа обычно выполняется в методе componentDidMount
жизненного цикла или в результате некоторого взаимодействия с пользователем.
Импортируйте authService
в компонент.
import authService from './api-authorization/AuthorizeService'
Извлеките и прикрепите маркер доступа к ответу
async populateWeatherData() {
const token = await authService.getAccessToken();
const response = await fetch('api/SampleData/WeatherForecasts', {
headers: !token ? {} : { 'Authorization': `Bearer ${token}` }
});
const data = await response.json();
this.setState({ forecasts: data, loading: false });
}
Развертывание в рабочей среде
Чтобы развернуть приложение в рабочей среде, необходимо подготовить следующие ресурсы:
- База данных для хранения Identity учетных записей пользователей и выдачи разрешений IdentityServer.
- Сертификат для использования в производстве, используемый для подписывания токенов.
- Для этого сертификата нет конкретных требований; это может быть самозаверяющий сертификат или сертификат, подготовленный центром сертификации.
- Его можно создать с помощью стандартных инструментов, таких как PowerShell или OpenSSL.
- Его можно установить в хранилище сертификатов целевых компьютеров или развернуть как файл .pfx с надежным паролем.
Пример. Развертывание в поставщике веб-размещения, отличном от Azure
В панели управления хостингом создайте или загрузите ваш сертификат. Затем в файле приложения appsettings.json
измените IdentityServer
раздел, чтобы включить сведения о ключе. Например:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "WebHosting",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
В предыдущем примере:
-
StoreName
представляет имя хранилища сертификатов, в котором хранится сертификат. В этом случае он указывает на магазин веб-хостинга. -
StoreLocation
представляет место загрузки сертификата (CurrentUser
в данном случае). -
Name
соответствует различаемой теме сертификата.
Пример: Развертывание в службу приложений Azure
В этом разделе описывается развертывание приложения в службе приложение Azure с помощью сертификата, хранящегося в хранилище сертификатов. Для изменения приложения, чтобы оно загружало сертификат из хранилища сертификатов, требуется план обслуживания уровня "Стандарт" или выше при настройке приложения в портале Azure на следующем шаге.
В файле приложения appsettings.json
измените IdentityServer
раздел, чтобы включить ключевые сведения:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "My",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
- Имя хранилища представляет имя хранилища сертификатов, в котором хранится сертификат. В этом случае указывается на личное хранилище пользователя.
- Расположение хранилища представляет место загрузки сертификата из (
CurrentUser
илиLocalMachine
). - Свойство имени в сертификате соответствует выделенному субъекту сертификата.
Чтобы развернуть службу приложение Azure, выполните действия, описанные в статье "Развертывание приложения в Azure", в котором объясняется, как создать необходимые ресурсы Azure и развернуть приложение в рабочей среде.
После выполнения предыдущих инструкций приложение развертывается в Azure, но еще не работает. Сертификат, используемый приложением, должен быть настроен в портал Azure. Найдите отпечаток сертификата и выполните действия, описанные в разделе "Загрузка сертификатов".
В то время как эти шаги упоминают SSL, в портал Azure есть раздел "Частные сертификаты", где можно отправить подготовленный сертификат для использования с приложением.
После настройки приложения и параметров приложения в портал Azure перезапустите приложение на портале.
Другие параметры конфигурации
Поддержка авторизации API строится на основе IdentityServer с набором соглашений, значений по умолчанию и усилений, которые упрощают работу с SPAs. Само собой разумеется, что все возможности IdentityServer доступны в фоновом режиме, если интеграция ASP.NET Core не охватывает ваш случай. Поддержка ASP.NET Core сосредоточена на внутренних приложениях, где все приложения создаются и развертываются нашей организацией. Таким образом, поддержка не предлагается для таких вещей, как согласие или федерация. Для этих сценариев используйте IdentityServer и следуйте их документации.
Профили приложений
Профили приложений — это предопределенные конфигурации для приложений, которые далее определяют их параметры. В настоящее время поддерживаются следующие профили:
-
IdentityServerSPA
: представляет SPA, размещенное вместе с IdentityServer как единое целое.- Значение
redirect_uri
по умолчанию устанавливается на/authentication/login-callback
. - Значение
post_logout_redirect_uri
по умолчанию/authentication/logout-callback
. - Набор областей включает
openid
profile
и каждую область, определенную для API в приложении. - Набор разрешенных типов ответов OIDC - это
id_token token
, или каждый из них по отдельности (id_token
,token
). - Допустимый режим ответа .
fragment
- Значение
-
SPA
: представляет SPA, который не размещается в IdentityServer.- Набор областей включает
openid
profile
и каждую область, определенную для API в приложении. - Набор разрешенных типов ответов OIDC - это
id_token token
, или каждый из них по отдельности (id_token
,token
). - Допустимый режим ответа .
fragment
- Набор областей включает
-
IdentityServerJwt
: представляет API, размещённый бок о бок с IdentityServer.- Приложение настроено на использование одной области, которая по умолчанию соответствует имени приложения.
-
API
: означает API, который не размещен в IdentityServer.- Приложение настроено на использование одной области, которая по умолчанию соответствует имени приложения.
Настройка с помощью AppSettings
Настройте приложения через систему конфигурации, добавив их в список Clients
или Resources
.
Настройте каждого клиента, его redirect_uri
свойство и post_logout_redirect_uri
свойство, как показано в следующем примере:
"IdentityServer": {
"Clients": {
"MySPA": {
"Profile": "SPA",
"RedirectUri": "https://www.example.com/authentication/login-callback",
"LogoutUri": "https://www.example.com/authentication/logout-callback"
}
}
}
При настройке ресурсов можно настроить области для ресурса, как показано ниже:
"IdentityServer": {
"Resources": {
"MyExternalApi": {
"Profile": "API",
"Scopes": "a b c"
}
}
}
Настройка с помощью кода
Вы также можете настроить клиентов и ресурсы через код, используя перегрузку AddApiAuthorization
, которая принимает действие для конфигурации параметров.
AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
options.Clients.AddSPA(
"My SPA", spa =>
spa.WithRedirectUri("http://www.example.com/authentication/login-callback")
.WithLogoutRedirectUri(
"http://www.example.com/authentication/logout-callback"));
options.ApiResources.AddApiResource("MyExternalApi", resource =>
resource.WithScopes("a", "b", "c"));
});
Дополнительные ресурсы
Шаблоны ASP.NET Core 3.1 и более поздних версий предлагают проверку подлинности в одностраничных приложениях (SPAs) с помощью поддержки авторизации API. ASP.NET Core Identity для проверки подлинности и хранения пользователей объединяется с IdentityServer для реализации OpenID Connect.
Параметр проверки подлинности был добавлен в шаблоны проектов Angular и React , аналогичные параметру проверки подлинности в шаблонах проектов веб-приложения (Model-View-Controller) (MVC) и веб-приложения (Razor Pages). Допустимые значения параметров — None и Individual. Шаблон проекта React.js и Redux не поддерживает параметр аутентификации на данный момент.
Создание приложения с поддержкой авторизации API
Аутентификацию пользователей и авторизацию можно использовать как с Angular, так и с React SPA. Откройте окно командной оболочки и выполните следующую команду:
Angular:
dotnet new angular -o <output_directory_name>
React:
dotnet new react -o <output_directory_name> -au Individual
Предыдущая команда создает приложение ASP.NET Core с каталогом ClientApp , содержащим SPA.
Общее описание основных компонентов приложения ASP.NET
В следующих разделах описываются дополнения к проекту при включенной поддержке проверки подлинности:
Класс Startup
В следующих примерах кода используется пакет NuGet Microsoft.AspNetCore.ApiAuthorization.IdentityServer . Примеры настраивают проверку подлинности и авторизации API с использованием методов расширения AddApiAuthorization и AddIdentityServerJwt. Проекты, использующие шаблоны проектов React или Angular SPA с проверкой подлинности, включают ссылку на этот пакет.
Класс Startup
имеет следующие дополнения:
Внутри метода
Startup.ConfigureServices
:Identity с пользовательским интерфейсом по умолчанию:
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlite(Configuration.GetConnectionString("DefaultConnection"))); services.AddDefaultIdentity<ApplicationUser>() .AddEntityFrameworkStores<ApplicationDbContext>();
IdentityServer с дополнительным
AddApiAuthorization
вспомогательным методом, который настраивает некоторые стандартные соглашения ASP.NET Core вдобавок к IdentityServer.services.AddIdentityServer() .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
Проверка подлинности с помощью дополнительного вспомогательного метода
AddIdentityServerJwt
, который настраивает приложение для проверки маркеров JWT, созданных IdentityServer:services.AddAuthentication() .AddIdentityServerJwt();
Внутри метода
Startup.Configure
:Промежуточное ПО для проверки подлинности, которое отвечает за проверку учетных данных запроса и установку пользователя в контексте запроса.
app.UseAuthentication();
Промежуточное программное обеспечение IdentityServer, которое предоставляет конечные точки OpenID Connect:
app.UseIdentityServer();
Предупреждение
В этой статье показано использование строк подключения. С локальной базой данных пользователю не нужно проходить проверку подлинности, но в production-среде строка подключения иногда включает пароль для проверки подлинности. Учетные данные владельца ресурса (ROPC) — это риск безопасности, который следует избежать в рабочих базах данных. Рабочие приложения должны использовать самый безопасный поток проверки подлинности. Дополнительные сведения о проверке подлинности для приложений, развернутых в тестовых или рабочих средах, см. в разделе "Безопасные потоки проверки подлинности".
Служба приложений Azure в Linux
Для развертываний службы приложений Azure на Linux укажите издателя явно в Startup.ConfigureServices
:
services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
options.Authority = "{AUTHORITY}";
});
В предыдущем коде заполнитель {AUTHORITY}
служит Authority для использования при вызовах OpenID Connect.
Пример:
options.Authority = "https://contoso-service.azurewebsites.net";
AddApiAuthorization
Этот вспомогательный метод настраивает IdentityServer для использования поддерживаемой конфигурации. IdentityServer — это функциональная и расширяемая платформа для устранения проблем с безопасностью приложений. В то же время это обеспечивает ненужную сложность для наиболее распространенных сценариев. Следовательно, вам предоставляется набор соглашений и параметров конфигурации, которые считаются хорошей отправной точкой. После изменения проверки подлинности полная мощность IdentityServer по-прежнему доступна для настройки проверки подлинности в соответствии с вашими потребностями.
AddIdentityServerJwt
Этот вспомогательный метод настраивает схему политики для приложения в качестве обработчика проверки подлинности по умолчанию. Политика настроена, чтобы разрешить Identity обрабатывать все запросы, перенаправленные в любой Identity подпуть в пространстве URL-адресов "/Identity".
JwtBearerHandler
обрабатывает все остальные запросы. Кроме того, этот метод регистрирует <<ApplicationName>>API
ресурс API в IdentityServer с областью <<ApplicationName>>API
по умолчанию и настраивает промежуточное ПО JWT Bearer для проверки токенов, выданных IdentityServer для приложения.
WeatherForecastController
В файле обратите внимание на атрибут, [Authorize]
примененный к классу, который указывает, что пользователю необходимо авторизоваться на основе политики по умолчанию для доступа к ресурсу. Политика авторизации по умолчанию настраивается для использования стандартной схемы проверки подлинности, которая устанавливается с помощью AddIdentityServerJwt
в схему политики, указанную выше, делая тем самым JwtBearerHandler
, сконфигурированным таким вспомогательным методом, обработчиком по умолчанию для запросов к приложению.
ApplicationDbContext
Обратите внимание, что в файле используется тот же самый DbContext
, что и в Identity, за исключением того, что он расширяет ApiAuthorizationDbContext
(более производный класс от IdentityDbContext
), чтобы включить схему для IdentityServer.
Чтобы получить полный контроль над схемой базы данных, наследуйте по одному из доступных IdentityDbContext
классов и настройте контекст для включения схемы Identity, вызывая метод builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value)
на OnModelCreating
.
OidcConfigurationController
В файле обратите внимание на конечную точку, подготовленную для обслуживания параметров OIDC, которые клиент должен использовать.
appsettings.json
appsettings.json
В файле корневого каталога проекта есть новый IdentityServer
раздел, описывающий список настроенных клиентов. В следующем примере есть один клиент. Имя клиента соответствует имени приложения и сопоставляется по соглашению с параметром ClientId
OAuth. Профиль указывает на настраиваемый тип приложения. Он используется внутри системы для управления соглашениями, упрощающими процесс настройки сервера. Существует несколько профилей, как описано в разделе "Профили приложений".
"IdentityServer": {
"Clients": {
"angularindividualpreview3final": {
"Profile": "IdentityServerSPA"
}
}
}
appsettings.Development.json
В файле корневого каталога проекта appsettings.Development.json
есть раздел IdentityServer
, который описывает ключ, используемый для подписания токенов. При развертывании в рабочей среде необходимо подготовить и развернуть ключ вместе с приложением, как описано в разделе "Развертывание в рабочей среде ".
"IdentityServer": {
"Key": {
"Type": "Development"
}
}
Общее описание приложения Angular
Поддержка проверки подлинности и авторизации API в шаблоне Angular находится в собственном модуле Angular в каталоге ClientApp/src/api-authorization . Модуль состоит из следующих элементов:
- 3 компонента:
-
login.component.ts
: обрабатывает поток входа приложения. -
logout.component.ts
: обрабатывает процесс выхода из приложения. -
login-menu.component.ts
: мини-приложение, отображающее один из следующих наборов ссылок:- Управление профилем пользователя и ссылки для выхода при аутентификации.
- Регистрация и вход по ссылкам, когда пользователь не проходит проверку подлинности.
-
- Защита
AuthorizeGuard
маршрута, которая может быть добавлена в маршруты и требует, чтобы пользователь прошел проверку подлинности перед посещением маршрута. - Перехватчик
AuthorizeInterceptor
HTTP, который присоединяет маркер доступа к исходящим HTTP-запросам, предназначенным для API, когда пользователь аутентифицирован. - Служба
AuthorizeService
, которая обрабатывает детали процесса аутентификации на более низком уровне и предоставляет информацию о пользователе, прошедшем проверку подлинности, для использования остальной частью приложения. - Модуль Angular, определяющий маршруты, связанные с частями проверки подлинности приложения. Он предоставляет компонент меню входа, перехватчик, защиту и сервис для использования остальной частью приложения.
Общее описание приложения React
Поддержка проверки подлинности и авторизации API в шаблоне React находится в каталоге ClientApp/src/components/api-authorization . Он состоит из следующих элементов:
- 4 компонента:
-
Login.js
: обрабатывает поток входа приложения. -
Logout.js
: обрабатывает процесс выхода из приложения. -
LoginMenu.js
: мини-приложение, отображающее один из следующих наборов ссылок:- Управление профилем пользователя и ссылки для выхода при аутентификации.
- Регистрация и вход по ссылкам, когда пользователь не проходит проверку подлинности.
-
AuthorizeRoute.js
: компонент маршрута, требующий проверки подлинности пользователя перед отрисовкой компонента, указанного в параметреComponent
.
-
- Экспортированный экземпляр
authService
классаAuthorizeService
, который обрабатывает более низкоуровневые детали процесса аутентификации и предоставляет информацию о прошедшем аутентификацию пользователе для использования остальной частью приложения.
Теперь, когда вы видели основные компоненты решения, вы можете более подробно ознакомиться с отдельными сценариями для приложения.
Требовать авторизацию в новом API
По умолчанию система настроена для упрощения авторизации для новых API. Для этого создайте новый контроллер и добавьте [Authorize]
атрибут в класс контроллера или в любое действие в контроллере.
Настройка обработчика проверки подлинности API
Чтобы настроить конфигурацию обработчика JWT API, установите параметры его JwtBearerOptions экземпляра.
services.AddAuthentication()
.AddIdentityServerJwt();
services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
...
});
Обработчик JWT API вызывает события, позволяющие управлять процессом проверки подлинности с помощью JwtBearerEvents
. Чтобы обеспечить поддержку авторизации API, AddIdentityServerJwt
регистрирует собственные обработчики событий.
Чтобы настроить обработку события, оберните существующий обработчик событий дополнительной логикой, если это необходимо. Например:
services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
var onTokenValidated = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
await onTokenValidated(context);
...
}
});
В приведенном выше коде OnTokenValidated
обработчик событий заменяется пользовательской реализацией. Эта реализация:
- Вызывает исходную реализацию, предоставляемую поддержкой авторизации API.
- Запуск собственной пользовательской логики.
Защита клиентской маршрутизации (Angular)
Защита клиентского маршрута выполняется путем добавления авторизации защиты в список гарантий, выполняемых при настройке маршрута. В качестве примера можно увидеть, как маршрут fetch-data
конфигурирован в модуле Angular главного приложения.
RouterModule.forRoot([
// ...
{ path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthorizeGuard] },
])
Важно отметить, что защита маршрута не защищает саму конечную точку (которая по-прежнему требует применения к ней атрибута [Authorize]
), а только запрещает пользователю переходить к заданному клиентскому маршруту, если пользователь не проходит проверку подлинности.
Проверка подлинности запросов API (Angular)
Проверка подлинности запросов к API, размещенным вместе с приложением, выполняется автоматически с помощью перехватчика HTTP-клиента, определенного приложением.
Защита клиентской маршрутизации (React)
Защита клиентского маршрута с помощью AuthorizeRoute
компонента вместо обычного Route
компонента. Например, обратите внимание, как fetch-data
маршрут настроен в компоненте App
:
<AuthorizeRoute path='/fetch-data' component={FetchData} />
Защита маршрута:
- Не защищает фактическую конечную точку (которая по-прежнему требует применения атрибута
[Authorize]
к нему). - Только не позволяет пользователю перейти на указанный маршрут клиентской стороны, если не выполнена аутентификация.
Проверка подлинности запросов API (React)
Проверка подлинности запросов с помощью React выполняется путем импорта экземпляра authService
из .AuthorizeService
Маркер доступа извлекается из authService
и добавляется к запросу, как показано ниже. В компонентах React эта работа обычно выполняется в методе componentDidMount
жизненного цикла или в результате некоторого взаимодействия с пользователем.
Импортируйте authService
в компонент.
import authService from './api-authorization/AuthorizeService'
Извлеките и прикрепите маркер доступа к ответу
async populateWeatherData() {
const token = await authService.getAccessToken();
const response = await fetch('api/SampleData/WeatherForecasts', {
headers: !token ? {} : { 'Authorization': `Bearer ${token}` }
});
const data = await response.json();
this.setState({ forecasts: data, loading: false });
}
Развертывание в рабочей среде
Чтобы развернуть приложение в рабочей среде, необходимо подготовить следующие ресурсы:
- База данных для хранения Identity учетных записей пользователей и выдачи разрешений IdentityServer.
- Сертификат для использования в производстве, используемый для подписывания токенов.
- Для этого сертификата нет конкретных требований; это может быть самозаверяющий сертификат или сертификат, подготовленный центром сертификации.
- Его можно создать с помощью стандартных инструментов, таких как PowerShell или OpenSSL.
- Его можно установить в хранилище сертификатов целевых компьютеров или развернуть как файл .pfx с надежным паролем.
Пример. Развертывание в поставщике веб-размещения, отличном от Azure
В панели управления хостингом создайте или загрузите ваш сертификат. Затем в файле приложения appsettings.json
измените IdentityServer
раздел, чтобы включить сведения о ключе. Например:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "WebHosting",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
В предыдущем примере:
-
StoreName
представляет имя хранилища сертификатов, в котором хранится сертификат. В этом случае он указывает на магазин веб-хостинга. -
StoreLocation
представляет место загрузки сертификата (CurrentUser
в данном случае). -
Name
соответствует различаемой теме сертификата.
Пример: Развертывание в службу приложений Azure
В этом разделе описывается развертывание приложения в службе приложение Azure с помощью сертификата, хранящегося в хранилище сертификатов. Для изменения приложения, чтобы оно загружало сертификат из хранилища сертификатов, требуется план обслуживания уровня "Стандарт" или выше при настройке приложения в портале Azure на следующем шаге.
В файле приложения appsettings.json
измените IdentityServer
раздел, чтобы включить ключевые сведения:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "My",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
- Имя хранилища представляет имя хранилища сертификатов, в котором хранится сертификат. В этом случае указывается на личное хранилище пользователя.
- Расположение хранилища представляет место загрузки сертификата из (
CurrentUser
илиLocalMachine
). - Свойство имени в сертификате соответствует выделенному субъекту сертификата.
Чтобы развернуть службу приложение Azure, выполните действия, описанные в статье "Развертывание приложения в Azure", в котором объясняется, как создать необходимые ресурсы Azure и развернуть приложение в рабочей среде.
После выполнения предыдущих инструкций приложение развертывается в Azure, но еще не работает. Сертификат, используемый приложением, должен быть настроен в портал Azure. Найдите отпечаток сертификата и выполните действия, описанные в разделе "Загрузка сертификатов".
В то время как эти шаги упоминают SSL, в портал Azure есть раздел "Частные сертификаты", где можно отправить подготовленный сертификат для использования с приложением.
После настройки приложения и параметров приложения в портал Azure перезапустите приложение на портале.
Другие параметры конфигурации
Поддержка авторизации API строится на основе IdentityServer с набором соглашений, значений по умолчанию и усилений, которые упрощают работу с SPAs. Само собой разумеется, полные возможности IdentityServer доступны в скрытом режиме, если интеграция ASP.NET Core не охватывает ваш сценарий. Поддержка ASP.NET Core сосредоточена на внутренних приложениях, где все приложения создаются и развертываются нашей организацией. Таким образом, поддержка не предлагается для таких вещей, как согласие или федерация. Для этих сценариев используйте IdentityServer и следуйте их документации.
Профили приложений
Профили приложений — это предопределенные конфигурации для приложений, которые далее определяют их параметры. В настоящее время поддерживаются следующие профили:
-
IdentityServerSPA
: представляет SPA, размещенное вместе с IdentityServer как единое целое.- Значение по умолчанию для
redirect_uri
—/authentication/login-callback
. - Значение
post_logout_redirect_uri
по умолчанию/authentication/logout-callback
. - Набор областей включает
openid
profile
и каждую область, определенную для API в приложении. - Набор разрешенных типов ответов OIDC - это
id_token token
, или каждый из них по отдельности (id_token
,token
). - Допустимый режим ответа .
fragment
- Значение по умолчанию для
-
SPA
: представляет spa, который не размещается в IdentityServer.- Набор областей включает
openid
profile
и каждую область, определенную для API в приложении. - Набор разрешенных типов ответов OIDC - это
id_token token
, или каждый из них по отдельности (id_token
,token
). - Допустимый режим ответа .
fragment
- Набор областей включает
-
IdentityServerJwt
: представляет API, размещённый бок о бок с IdentityServer.- Приложение настроено на использование одной области, которая по умолчанию соответствует имени приложения.
-
API
: представляет API, который не размещен на платформе IdentityServer.- Приложение настроено на использование одной области, которая по умолчанию соответствует имени приложения.
Настройка с помощью AppSettings
Настройте приложения через систему конфигурации, добавив их в список Clients
или Resources
.
Настройте каждого клиента, его redirect_uri
свойство и post_logout_redirect_uri
свойство, как показано в следующем примере:
"IdentityServer": {
"Clients": {
"MySPA": {
"Profile": "SPA",
"RedirectUri": "https://www.example.com/authentication/login-callback",
"LogoutUri": "https://www.example.com/authentication/logout-callback"
}
}
}
При настройке ресурсов можно настроить области для ресурса, как показано ниже:
"IdentityServer": {
"Resources": {
"MyExternalApi": {
"Profile": "API",
"Scopes": "a b c"
}
}
}
Настройка с помощью кода
Вы также можете настроить клиентов и ресурсы через код, используя перегрузку AddApiAuthorization
, которая принимает действие для конфигурации параметров.
AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
options.Clients.AddSPA(
"My SPA", spa =>
spa.WithRedirectUri("http://www.example.com/authentication/login-callback")
.WithLogoutRedirectUri(
"http://www.example.com/authentication/logout-callback"));
options.ApiResources.AddApiResource("MyExternalApi", resource =>
resource.WithScopes("a", "b", "c"));
});
Дополнительные ресурсы
ASP.NET Core