Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Область применения: арендаторы рабочей силы
внешние арендаторы (узнать больше)
В этом руководстве показано, как защитить веб-API ASP.NET Core с помощью платформы удостоверений Майкрософт, чтобы ограничить доступ только авторизованным пользователям и клиентским приложениям. Веб-API, который вы создаете, использует делегированные разрешения (области) и разрешения приложения (роли приложения).
Изучив это руководство, вы:
- Создание веб-API ASP.NET Core
- Настройка веб-API для использования сведений о регистрации приложения Microsoft Entra
- Защита конечных точек веб-API
- Запустите веб-API, чтобы убедиться, что он прослушивает HTTP-запросы
Предпосылки
- Если вы еще не сделали этого, выполните шаги из краткого руководства: Вызов веб-API, защищенного платформой удостоверений Microsoft. Вам не нужно клонировать и запускать пример кода, но убедитесь, что у вас есть следующее:
- Сведения о регистрации приложения веб-API из Центра администрирования Microsoft Entra, включая идентификатор клиента и идентификатор арендатора.
- ToDoList.Read и ToDoList.ReadWrite в качестве делегированных разрешений (областей), предоставляемых веб-API
- ToDoList.Read.All и ToDoList.ReadWrite.All как разрешения приложения (роли приложения), предоставляемые веб-API
- Пакет SDK для .NET 8.0 или более поздней версии.
- Visual Studio Code или другой редактор кода.
Создание проекта веб-API ASP.NET Core
Чтобы создать минимальный проект веб-API на основе ASP.NET Core, выполните следующие действия.
Откройте терминал в Visual Studio Code или любом другом редакторе кода и перейдите в каталог, в котором вы хотите создать проект.
Выполните следующие команды в интерфейсе командной строки .NET или любом другом средстве командной строки.
dotnet new web -o TodoListApi cd TodoListApi
Выберите "Да ", когда диалоговое окно спрашивает, хотите ли вы доверять авторам.
Выберите "Да" , когда диалоговое окно запрашивает, нужно ли добавить необходимые ресурсы в проект.
Установка необходимых пакетов
Чтобы создать, защитить и протестировать веб-API ASP.NET Core, необходимо установить следующие пакеты:
-
Microsoft.EntityFrameworkCore.InMemory
— пакет, позволяющий использовать Entity Framework Core с базой данных в памяти. Это полезно для тестирования, но не предназначено для использования в рабочей среде. -
Microsoft.Identity.Web
— набор библиотек ASP.NET Core, упрощающий добавление поддержки проверки подлинности и авторизации в веб-приложения и веб-API, которые интегрируются с платформой удостоверений Майкрософт.
Чтобы установить пакет, используйте следующую команду:
dotnet add package Microsoft.EntityFrameworkCore.InMemory
dotnet add package Microsoft.Identity.Web
Настройка сведений о регистрации приложения
Откройте файлappsettings.json в папке приложения и добавьте сведения о регистрации приложения, записанные после регистрации веб-API.
{
"AzureAd": {
"Instance": "Enter_the_Authority_URL_Here",
"TenantId": "Enter_the_Tenant_Id_Here",
"ClientId": "Enter_the_Application_Id_Here"
},
"Logging": {...},
"AllowedHosts": "*"
}
Замените следующие заполнители, как показано ниже:
- Замените
Enter_the_Application_Id_Here
идентификатором приложения (клиента). - Замените
Enter_the_Tenant_Id_Here
идентификатором каталога (клиента). - Замените
Enter_the_Authority_URL_Here
вашим URL-адресом авторитета, как описано в следующем разделе.
URL-адрес авторизации для вашего приложения
URL-адрес центра указывает каталог, из которого библиотека проверки подлинности Microsoft (MSAL) может запрашивать токены. Вы подходите к формированию команды и взаимодействию с арендаторами по-разному, как показано.
//Instance for workforce tenant
Instance: "https://login.microsoftonline.com/"
Использование личного домена URL-адреса (необязательно)
Домены пользовательского URL-адреса не поддерживаются в клиентах рабочей силы.
Добавление разрешений
Все API-интерфейсы должны публиковать как минимум одну область, также называемую делегированным разрешением, чтобы клиентские приложения могли успешно получить токен доступа для пользователя. API также должны публиковать как минимум одну роль приложения, также называемую разрешениями приложения, чтобы клиентские приложения получали токен доступа сами по себе, то есть если они не входят в систему пользователя.
Мы указываем эти разрешения в файлеappsettings.json . В этом руководстве вы зарегистрировали следующие разрешения: делегированные и для приложения.
- Делегированные разрешения:ToDoList.Read и ToDoList.ReadWrite.
- Разрешения приложений:ToDoList.Read.All и ToDoList.ReadWrite.All.
Когда пользователь или клиентское приложение вызывает веб-API, доступ к защищенной конечной точке получают только клиенты с этими областями или разрешениями.
{
"AzureAd": {
"Instance": "Enter_the_Authority_URL_Here",
"TenantId": "Enter_the_Tenant_Id_Here",
"ClientId": "Enter_the_Application_Id_Here",
"Scopes": {
"Read": ["ToDoList.Read", "ToDoList.ReadWrite"],
"Write": ["ToDoList.ReadWrite"]
},
"AppPermissions": {
"Read": ["ToDoList.Read.All", "ToDoList.ReadWrite.All"],
"Write": ["ToDoList.ReadWrite.All"]
}
},
"Logging": {...},
"AllowedHosts": "*"
}
Реализация проверки подлинности и авторизации в API
Чтобы настроить проверку подлинности и авторизацию, откройте program.cs
файл и замените его содержимое следующими фрагментами кода:
Добавление схемы проверки подлинности
В этом API мы используем схему носителя веб-маркера JSON (JWT) в качестве механизма проверки подлинности по умолчанию. Используйте метод AddAuthentication
для регистрации схемы токен-носителя JWT.
// Add required packages to your imports
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Add an authentication scheme
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration);
Создание модели приложения
В корневой папке проекта создайте папку с именем Models. Перейдите в папку Models и создайте файл с именем ToDo.cs
, а затем добавьте следующий код.
using System;
namespace ToDoListAPI.Models;
public class ToDo
{
public int Id { get; set; }
public Guid Owner { get; set; }
public string Description { get; set; } = string.Empty;
}
Предыдущий код создает модель с именем ToDo. Эта модель представляет данные, которыми управляет приложение.
Добавление контекста базы данных
Затем мы определим класс контекста базы данных, который координирует функциональные возможности Entity Framework для модели данных. Этот класс наследует от класса Microsoft.EntityFrameworkCore.DbContext , который управляет взаимодействием между приложением и базой данных. Чтобы добавить контекст базы данных, выполните следующие действия.
Создайте папку с именем DbContext в корневой папке проекта.
Перейдите в папку DbContext и создайте файл с именем
ToDoContext.cs
, а затем добавьте следующий код:using Microsoft.EntityFrameworkCore; using ToDoListAPI.Models; namespace ToDoListAPI.Context; public class ToDoContext : DbContext { public ToDoContext(DbContextOptions<ToDoContext> options) : base(options) { } public DbSet<ToDo> ToDos { get; set; } }
Откройте файл Program.cs в корневой папке проекта и обновите его следующим кодом:
// Add the following to your imports using ToDoListAPI.Context; using Microsoft.EntityFrameworkCore; //Register ToDoContext as a service in the application builder.Services.AddDbContext<ToDoContext>(opt => opt.UseInMemoryDatabase("ToDos"));
В приведенном выше фрагменте кода мы регистрируем контекст базы данных в качестве службы с областью действия в поставщике служб приложений ASP.NET Core (также называемом контейнером внедрения зависимостей). Вы также настраиваете ToDoContext
класс для использования базы данных в оперативной памяти для API списка ToDo.
Настройка контроллера
Контроллеры обычно реализуют действия создания, чтения, обновления и удаления (CRUD) для управления ресурсами. Так как в этом руководстве основное внимание уделяется защите конечных точек API, мы реализуем только два элемента действия в контроллере. Действие "Чтение всех" для получения всех элементов To-Do и действие "Создать" для добавления нового элемента To-Do. Выполните следующие действия, чтобы добавить контроллер в проект:
Перейдите в корневую папку проекта и создайте папку с именем Контроллеры.
Создайте файл с именем
ToDoListController.cs
в папке Контроллеры и добавьте следующий шаблонный код:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.Resource;
using ToDoListAPI.Models;
using ToDoListAPI.Context;
namespace ToDoListAPI.Controllers;
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class ToDoListController : ControllerBase
{
private readonly ToDoContext _toDoContext;
public ToDoListController(ToDoContext toDoContext)
{
_toDoContext = toDoContext;
}
[HttpGet()]
[RequiredScopeOrAppPermission()]
public async Task<IActionResult> GetAsync(){...}
[HttpPost]
[RequiredScopeOrAppPermission()]
public async Task<IActionResult> PostAsync([FromBody] ToDo toDo){...}
private bool RequestCanAccessToDo(Guid userId){...}
private Guid GetUserId(){...}
private bool IsAppMakingRequest(){...}
}
Добавление кода в контроллер
В этом разделе объясняется, как добавить код в шаблон контроллера в предыдущем разделе. Основное внимание уделяется защите API, а не его созданию.
Импортируйте необходимые пакеты: Пакет
Microsoft.Identity.Web
представляет собой оболочку вокруг MSAL.NET, которая помогает легко обрабатывать логику проверки подлинности, например обработку проверки маркеров. Чтобы гарантировать, что для наших конечных точек требуется авторизация, мы используем встроенныйMicrosoft.AspNetCore.Authorization
пакет.Так как мы предоставили разрешения для вызова этого API с помощью делегированных разрешений от имени пользователя или приложения, где клиент вызывает себя, а не от имени пользователя, важно знать, выполняется ли вызов приложением от собственного имени. Самый простой способ сделать это — определить, содержит ли маркер доступа необязательное утверждение
idtyp
. Этоidtyp
утверждение является самым простым способом для API определить, является ли токен токеном приложения или токеном приложения с пользователем. Мы рекомендуем включить необязательноеidtyp
утверждение.Если
idtyp
утверждение не активировано, можно использоватьroles
иscp
утверждения, чтобы определить, является ли токен доступа токеном приложения или токеном приложения и пользователя. Токен доступа, выданный службой идентификации Microsoft Entra ID, содержит как минимум одно из двух утверждений. Маркеры доступа, выданные пользователю, имеют требованиеscp
. Токены доступа, выданные приложению, имеют утверждениеroles
. Маркеры доступа, содержащие оба утверждения, выдаются только пользователям, гдеscp
утверждение назначает делегированные разрешения, аroles
утверждение обозначает роль пользователя. Маркеры доступа, которые не обладают необходимыми свойствами, не должны учитываться.private bool IsAppMakingRequest() { if (HttpContext.User.Claims.Any(c => c.Type == "idtyp")) { return HttpContext.User.Claims.Any(c => c.Type == "idtyp" && c.Value == "app"); } else { return HttpContext.User.Claims.Any(c => c.Type == "roles") && !HttpContext.User.Claims.Any(c => c.Type == "scp"); } }
Добавьте вспомогающую функцию, которая определяет, содержит ли запрос достаточно разрешений для выполнения предполагаемого действия. Проверьте, выполняет ли приложение запрос от собственного имени или выполняет ли приложение вызов от имени пользователя, который владеет заданным ресурсом, проверяя идентификатор пользователя.
private bool RequestCanAccessToDo(Guid userId) { return IsAppMakingRequest() || (userId == GetUserId()); } private Guid GetUserId() { Guid userId; if (!Guid.TryParse(HttpContext.User.GetObjectId(), out userId)) { throw new Exception("User ID is not valid."); } return userId; }
Подключите определения разрешений для защиты маршрутов. Защитите API, добавив
[Authorize]
атрибут в класс контроллера. Это гарантирует, что действия контроллера можно вызывать только в том случае, если API вызывается с авторизованным удостоверением. Определения разрешений определяют, какие типы разрешений необходимы для выполнения этих действий.[Authorize] [Route("api/[controller]")] [ApiController] public class ToDoListController: ControllerBase{...}
Добавьте разрешения для конечных точек GET и POST. Для этого используется метод RequiredScopeOrAppPermission , который входит в пространство имен Microsoft.Identity.Web.Resource . Затем вы передаете области и разрешения этому методу с помощью атрибутов RequiredScopesConfigurationKey и RequiredAppPermissionsConfigurationKey .
[HttpGet] [RequiredScopeOrAppPermission( RequiredScopesConfigurationKey = "AzureAD:Scopes:Read", RequiredAppPermissionsConfigurationKey = "AzureAD:AppPermissions:Read" )] public async Task<IActionResult> GetAsync() { var toDos = await _toDoContext.ToDos! .Where(td => RequestCanAccessToDo(td.Owner)) .ToListAsync(); return Ok(toDos); } [HttpPost] [RequiredScopeOrAppPermission( RequiredScopesConfigurationKey = "AzureAD:Scopes:Write", RequiredAppPermissionsConfigurationKey = "AzureAD:AppPermissions:Write" )] public async Task<IActionResult> PostAsync([FromBody] ToDo toDo) { // Only let applications with global to-do access set the user ID or to-do's var ownerIdOfTodo = IsAppMakingRequest() ? toDo.Owner : GetUserId(); var newToDo = new ToDo() { Owner = ownerIdOfTodo, Description = toDo.Description }; await _toDoContext.ToDos!.AddAsync(newToDo); await _toDoContext.SaveChangesAsync(); return Created($"/todo/{newToDo!.Id}", newToDo); }
Настройка ПО промежуточного слоя API для использования контроллера
Затем мы настраиваем приложение для распознавания и использования контроллеров для обработки HTTP-запросов.
program.cs
Откройте файл и добавьте следующий код, чтобы зарегистрировать службы контроллера в контейнере внедрения зависимостей.
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
В приведенном выше фрагменте кода метод подготавливает приложение к использованию контроллеров путем AddControllers()
регистрации необходимых служб во время MapControllers()
сопоставления маршрутов контроллера для обработки входящих HTTP-запросов.
Запуск API
Запустите API, чтобы убедиться, что он работает без ошибок с помощью команды dotnet run
. Если вы планируете использовать протокол HTTPS даже во время тестирования, необходимо доверять сертификату разработки .NET.
Запустите приложение, введя следующее в терминале:
dotnet run
В терминале должны отображаться выходные данные, аналогичные приведенным ниже, что подтверждает, что приложение запущено на
http://localhost:{port}
и прослушивает запросы.Building... info: Microsoft.Hosting.Lifetime[0] Now listening on: http://localhost:{port} info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. ...
Веб-страница http://localhost:{host}
отображает выходные данные, аналогичные следующему изображению. Это связано с тем, что API вызывается без проверки подлинности. Чтобы выполнить авторизованный вызов, ознакомьтесь со следующими инструкциями по доступу к защищенному веб-API.
Полный пример этого кода API см. в файле примеров.