Megosztás a következőn keresztül:


Oktatóanyag: ASP.NET Core webes API létrehozása és védelme a Microsoft identitásplatformjával

A következőkre vonatkozik: Zöld kör fehér pipa szimbólummal, amely a következő tartalmat jelzi a munkaerő-bérlőkre. A munkaerő-bérlők zöld körrel, fehér pipa jellel, amely a következő tartalmat jelzi a külső bérlőkre. Külső bérlők (további információ)

Ez az oktatóanyag-sorozat bemutatja, hogyan védhet meg egy ASP.NET Core webes API-t a Microsoft identitásplatformjával, hogy csak a jogosult felhasználók és ügyfélalkalmazások számára korlátozza a hozzáférést. A létrehozott webes API delegált engedélyeket (hatóköröket) és alkalmazásengedélyeket (alkalmazásszerepköröket) használ.

Ebben az oktatóanyagban ön:

  • ASP.NET Core webes API létrehozása
  • A webes API konfigurálása a Microsoft Entra alkalmazásregisztrációs adatainak használatára
  • A webes API-végpontok védelme
  • Indítsa el a webes API-t, hogy az készen álljon a HTTP-kérések fogadására.

Előfeltételek

Új ASP.NET Core webes API-projekt létrehozása

Egy minimális ASP.NET Core webes API-projekt létrehozásához kövesse az alábbi lépéseket:

  1. Nyissa meg a terminált a Visual Studio Code-on vagy bármely más kódszerkesztőben, és keresse meg azt a könyvtárat, ahol létre szeretné hozni a projektet.

  2. Futtassa az alábbi parancsokat a .NET CLI-n vagy bármely más parancssori eszközön.

    dotnet new web -o TodoListApi
    cd TodoListApi
    
  3. Válassza az Igen lehetőséget, amikor egy párbeszédpanel megkérdezi, hogy megbízik-e a szerzőkben.

  4. Válassza az Igen lehetőséget, ha egy párbeszédpanel megkérdezi, hogy szeretné-e hozzáadni a szükséges eszközöket a projekthez.

A szükséges csomagok telepítése

A ASP.NET Core webes API létrehozásához, védelméhez és teszteléséhez telepítenie kell a következő csomagokat:

  • Microsoft.EntityFrameworkCore.InMemory- Egy csomag, amely lehetővé teszi az Entity Framework Core memórián belüli adatbázissal való használatát. Tesztelési célokra hasznos, de nem üzemi használatra tervezték.
  • Microsoft.Identity.Web - ASP.NET Alapvető kódtárak készlete, amelyek leegyszerűsítik a hitelesítés és az engedélyezés támogatását a Microsoft identitásplatformjával integrálható webalkalmazásokhoz és webes API-khoz.

A csomag telepítéséhez használja a következőt:

dotnet add package Microsoft.EntityFrameworkCore.InMemory
dotnet add package Microsoft.Identity.Web

Alkalmazásregisztrációs adatok konfigurálása

Nyissa meg a appsettings.json fájlt az alkalmazásmappában, és adja hozzá a webes API regisztrálása után rögzített alkalmazásregisztrációs adatokat.

{
    "AzureAd": {
        "Instance": "Enter_the_Authority_URL_Here",
        "TenantId": "Enter_the_Tenant_Id_Here",
        "ClientId": "Enter_the_Application_Id_Here"
    },
    "Logging": {...},
  "AllowedHosts": "*"
}

Cserélje le a következő helyőrzőket az ábrán látható módon:

  • Cserélje le a Enter_the_Application_Id_Here helyére az alkalmazás (ügyfél) azonosítóját.
  • Cserélje le a Enter_the_Tenant_Id_Here értékét a címtár (bérlő) azonosítójával.
  • Helyettesítse a Enter_the_Authority_URL_Here helyett a jogosultsági URL-címet, ahogy az a következő szakaszban ismertetve van.

Az alkalmazás hatósági URL-címe

A szolgáltató URL-címe határozza meg azt a könyvtárat, amelytől a Microsoft Authentication Library (MSAL) jogkivonatokat kérhet. Ezt a munkaerőben és a külső bérlőkben is másképp kell felépíteni, ahogy az alábbi ábrán látható:

//Instance for workforce tenant
Instance: "https://login.microsoftonline.com/"

Egyéni URL-tartomány használata (nem kötelező)

Az egyéni URL-tartományok nem támogatottak a munkaerő-bérlőkben.

Engedélyek hozzáadása

Minden API-nak közzé kell tennie legalább egy hatókört, más néven delegált engedélyt, hogy az ügyfélalkalmazások sikeresen beszerezhessék a felhasználó hozzáférési jogkivonatát. Az API-knak legalább egy alkalmazásszerepkört, más néven alkalmazásengedélyt kell közzétenniük ahhoz, hogy az ügyfélalkalmazások saját maguk szerezzék be a hozzáférési jogkivonatot, vagyis ha nem jelentkeznek be egy felhasználóba.

Ezeket az engedélyeket a appsettings.json fájlban adhatja meg. Ebben az oktatóanyagban a következő delegált és alkalmazásengedélyeket regisztrálta:

  • Delegált engedélyek:ToDoList.Read és ToDoList.ReadWrite.
  • Alkalmazásengedélyek:ToDoList.Read.All és ToDoList.ReadWrite.All.

Amikor egy felhasználó vagy ügyfélalkalmazás meghívja a webes API-t, csak az ilyen hatókörökkel vagy engedélyekkel rendelkező ügyfelek férhetnek hozzá a védett végponthoz.

{
  "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": "*"
}

Hitelesítés és engedélyezés implementálása az API-ban

A hitelesítés és az engedélyezés konfigurálásához nyissa meg a program.cs fájlt, és cserélje le a tartalmát a következő kódrészletekre:

Hitelesítési séma hozzáadása

Ebben az API-ban a JSON Web Token (JWT) Tulajdonosi sémát használjuk alapértelmezett hitelesítési mechanizmusként. Ezzel a AddAuthentication módszerrel regisztrálhatja a JWT tulajdonosi sémát.

// 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);

Az alkalmazás modelljének létrehozása

A projekt gyökérmappájában hozzon létre egy Modellek nevű mappát. Lépjen a Models mappába, és hozzon létre egy nevű ToDo.cs fájlt, majd adja hozzá a következő kódot.

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;
}

Az előző kód létrehoz egy ToDo nevű modellt. Ez a modell az alkalmazás által kezelt adatokat jelöli.

Adatbázis-környezet hozzáadása

Ezután meghatározunk egy adatbázis-környezeti osztályt, amely egy adatmodell Entity Framework funkcióját koordinálja. Ez az osztály a Microsoft.EntityFrameworkCore.DbContext osztálytól öröklődik, amely kezeli az alkalmazás és az adatbázis közötti interakciókat. Az adatbázis-környezet hozzáadásához kövesse az alábbi lépéseket:

  1. Hozzon létre egy DbContext nevű mappát a projekt gyökérmappájában.

  2. Lépjen a DbContext mappába, és hozzon létre egy nevű ToDoContext.cs fájlt, majd adja hozzá a következő kódot:

    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; }
    }
    
  3. Nyissa meg a Program.cs fájlt a projekt gyökérmappájában, és frissítse a következő kóddal:

    // 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"));
    

Az előző kódrészletben a DB-környezetet hatóköralapú szolgáltatásként regisztráljuk a ASP.NET Core alkalmazásszolgáltatóban (más néven a függőséginjektálási tárolóban). Az osztályt ToDoContext úgy is konfigurálhatja, hogy memóriabeli adatbázist használjon a ToDo List API-hoz.

Vezérlő beállítása

A vezérlők általában létrehozási, olvasási, frissítési és törlési (CRUD) műveleteket implementálnak az erőforrások kezeléséhez. Mivel ez az oktatóanyag az API-végpontok védelmére összpontosít, csak két műveletelemet implementálunk a vezérlőben. Egy 'Olvasás' művelet visszakeresi az összes To-Do elemet, és egy 'Létrehozás' művelet hozzáad egy új To-Do elemet. Az alábbi lépéseket követve adhat hozzá vezérlőt a projekthez:

  1. Lépjen a projekt gyökérmappájára, és hozzon létre egy Vezérlők nevű mappát.

  2. Hozzon létre egy fájlt ToDoListController.cs a Controllers mappában, és adja hozzá a következő kazánlemez-kódot:

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(){...}
}

Kód hozzáadása a vezérlőhöz

Ez a szakasz bemutatja, hogyan adhat hozzá kódot az előző szakaszban állványozott vezérlőhöz. Itt az API védelmén van a hangsúly, nem pedig az összeállításon.

  1. Importálja a szükséges csomagokat: A Microsoft.Identity.Web csomag egy burkoló a MSAL.NET körül, amely segít könnyen kezelni a hitelesítési logikát, például a jogkivonatok érvényesítésének kezelését. Annak érdekében, hogy a végpontok hitelesítést igényeljenek, a beépített Microsoft.AspNetCore.Authorization csomagot használjuk.

  2. Mivel engedélyt adtunk ahhoz, hogy az API-t delegált engedélyekkel hívjuk meg a felhasználó vagy alkalmazásengedélyek nevében, ahol az ügyfél maga hívja meg a hívást, és nem a felhasználó nevében, fontos tudni, hogy az alkalmazás a saját nevében kezdeményezi-e a hívást. Ennek legegyszerűbb módja annak megállapítása, hogy a hozzáférési jogkivonat tartalmazza-e az idtyp opcionális jogcímet. Ez idtyp a jogcím a legegyszerűbb módja annak megállapításának, hogy egy jogkivonat alkalmazásjogkivonat vagy alkalmazás+ felhasználói jogkivonat-e. Javasoljuk, hogy engedélyezze az idtyp opcionális jogcímet.

    Ha a idtyp jogcím nincs engedélyezve, a rolesscp jogcímekkel megállapíthatja, hogy a hozzáférési jogkivonat egy alkalmazásjogkivonat vagy egy alkalmazás+ felhasználói jogkivonat. A Microsoft Entra ID által kibocsátott hozzáférési jogkivonat a két jogcím legalább egyikével rendelkezik. A felhasználónak kibocsátott hozzáférési jogkivonatok rendelkeznek a scp jogcímmel. Az alkalmazás számára kibocsátott hozzáférési jogkivonatok rendelkeznek a roles jogcímel. A mindkét jogcímet tartalmazó hozzáférési jogkivonatok csak a felhasználók számára vannak kiadva, ahol a scp jogcím a delegált engedélyeket jelöli ki, míg a roles jogcím a felhasználó szerepkörét jelöli ki. Azokat a hozzáférési jogkivonatokat, amelyekhez semmi sem tartozik, nem kell tiszteletben tartani.

    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");
        }
    }
    
  3. Adjon hozzá egy segédfüggvényt, amely meghatározza, hogy a kérés elegendő engedélyt tartalmaz-e a kívánt művelet végrehajtásához. Ellenőrizze, hogy az alkalmazás a saját nevében küldi-e el a kérést, vagy az alkalmazás a felhasználóazonosító érvényesítésével ellenőrzi, hogy az adott erőforrás tulajdonosa nevében kezdeményezi-e a hívást.

    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;
        }
    
  4. Az útvonalak védelméhez csatlakoztassa az engedélydefiníciókat. Az API védelméhez adja hozzá az [Authorize] attribútumot a vezérlőosztályhoz. Ez biztosítja, hogy a vezérlőműveletek csak akkor hívhatók meg, ha az API-t hitelesített identitással hívják meg. Az engedélydefiníciók határozzák meg, hogy milyen típusú engedélyekre van szükség ezeknek a műveleteknek a végrehajtásához.

    [Authorize]
    [Route("api/[controller]")]
    [ApiController]
    public class ToDoListController: ControllerBase{...}
    

    Engedélyek hozzáadása a GET és POST végpontokhoz. Ezt a Microsoft.Identity.Web.Resource névtér részét képező RequiredScopeOrAppPermission metódussal teheti meg. Ezután a RequiredScopesConfigurationKey és a RequiredAppPermissionsConfigurationKey attribútumokkal adhat át hatóköröket és engedélyeket ehhez a metódushoz.

    [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);
    }
    

Az API köztes szoftver konfigurálása a vezérlő használatára

Ezután konfiguráljuk az alkalmazást úgy, hogy felismerje és használjon vezérlőket a HTTP-kérések kezeléséhez. Nyissa meg a program.cs fájlt, és adja hozzá a következő kódot a vezérlőszolgáltatásoknak a függőséginjektálási tárolóban való regisztrálásához.


builder.Services.AddControllers();

var app = builder.Build();
app.MapControllers();

app.Run();

Az előző kódrészletben a AddControllers() metódus előkészíti az alkalmazást a vezérlők használatára a szükséges szolgáltatások regisztrálásával, miközben MapControllers() leképezi a vezérlő útvonalait a bejövő HTTP-kérések kezeléséhez.

Az API futtatása

Futtassa az API-t a parancs dotnet run használatával, hogy megbizonyosodjon arról, hogy hiba nélkül fut. Ha a tesztelés során is HTTPS protokollt kíván használni, meg kell bíznia a .NET fejlesztési tanúsítványban.

  1. Indítsa el az alkalmazást úgy, hogy beírja a következőt a terminálba:

    dotnet run
    
  2. A terminálon az alábbihoz hasonló kimenetnek kell megjelennie, amely megerősíti, hogy az alkalmazás fut, http://localhost:{port} és figyeli a kéréseket.

    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.
    ...
    

A weblap http://localhost:{host} az alábbi képhez hasonló kimenetet jelenít meg. Ennek az az oka, hogy az API hitelesítés nélkül van meghívva. Egy engedélyezett hívás indításához tekintse meg a következő lépéseket a védett webes API-k elérésére vonatkozó útmutatásért.

képernyőkép, amely a 401-et jeleníti meg a weblap indításakor.

Az API-kódra vonatkozó teljes példáért tekintse meg a mintafájlt.

Következő lépések