Aracılığıyla paylaş


Öğretici: Microsoft kimlik platformu ile ASP.NET Core web API'sini oluşturma ve güvenliğini sağlama

için geçerlidir: Yeşil daire, beyaz onay işareti simgesiyle . Workforce kiracıları için yeşil daire, beyaz onay işareti simgesiyle . dış kiracılar için (daha fazla bilgi)

Bu öğretici serisi, ASP.NET Core web API'sinin yalnızca yetkili kullanıcılar ve istemci uygulamalarıyla erişimini sınırlamak için Microsoft kimlik platformuyla nasıl korunduğunu gösterir. Oluşturduğunuz web API'sinde hem temsilci izinleri (kapsamlar) hem de uygulama izinleri (uygulama rolleri) kullanılır.

Bu eğitimde, siz:

  • ASP.NET Core web API'si oluşturma
  • Web API'sini Microsoft Entra uygulama kayıt ayrıntılarını kullanacak şekilde yapılandırma
  • Web API'nizin uç noktalarını koruma
  • HTTP isteklerini dinlediğinden emin olmak için web API'sini çalıştırın

Önkoşullar

Yeni ASP.NET Core web API'si projesi oluşturma

En az ASP.NET Core web API projesi oluşturmak için şu adımları izleyin:

  1. Terminalinizi Visual Studio Code'da veya başka bir kod düzenleyicisinde açın ve projenizi oluşturmak istediğiniz dizine gidin.

  2. .NET CLI veya başka bir komut satırı aracında aşağıdaki komutları çalıştırın.

    dotnet new web -o TodoListApi
    cd TodoListApi
    
  3. bir iletişim kutusu yazarlara güvenmek isteyip istemediğinizi sorduğunda Evet 'i seçin.

  4. bir iletişim kutusu gerekli varlıkları projeye eklemek isteyip istemediğinizi sorduğunda evet seçin.

Gerekli paketleri yükleme

ASP.NET Core web API'sini oluşturmak, korumak ve test etmek için aşağıdaki paketleri yüklemeniz gerekir:

  • Microsoft.EntityFrameworkCore.InMemory- Entity Framework Core'un bellek içi veritabanıyla kullanılmasını sağlayan paket. Test amacıyla kullanışlıdır ancak üretim kullanımı için tasarlanmamıştır.
  • Microsoft.Identity.Web - Microsoft kimlik platformuyla tümleşen web uygulamalarına ve web API'lerine kimlik doğrulaması ve yetkilendirme desteği eklemeyi basitleştiren bir dizi ASP.NET Core kitaplığı.

Paketi yüklemek için şunu kullanın:

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

Uygulama kaydı ayrıntılarını yapılandırma

Uygulama klasörünüzde appsettings.json dosyasını açın ve web API'sini kaydettikten sonra kaydettiğiniz uygulama kayıt ayrıntılarını ekleyin.

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

Aşağıdaki yer tutucuları gösterildiği gibi değiştirin:

  • Enter_the_Application_Id_Here yerine uygulama (istemci) kimliğinizi girin.
  • Enter_the_Tenant_Id_Here değerini Dizin (kiracı) kimliğiniz ile değiştirin.
  • sonraki bölümde açıklandığı gibi Enter_the_Authority_URL_Here Yetkili URL'nizle değiştirin.

Uygulamanızın yetkili URL'si

Yetkili URL'si, Microsoft Kimlik Doğrulama Kitaplığı'nın (MSAL) belirteç isteğinde bulunabileceği dizini belirtir. Hem çalışma gücü hem de dış kiracılarda, gösterildiği gibi farklı şekilde inşa edebilirsiniz.

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

Özel URL alan adı kullanın (İsteğe bağlı)

Özel URL alan adları iş gücü ortamlarında desteklenmez.

İzin ekleme

İstemci uygulamalarının bir kullanıcı için başarıyla erişim belirteci alabilmesi için tüm API'lerin temsilci izni olarak da adlandırılan en az bir kapsam yayımlaması gerekir. API'ler, istemci uygulamaların bir kullanıcıda oturum açmadıkları durumlarda kendileri olarak bir erişim belirteci elde edebilmeleri için, uygulama izinleri olarak da adlandırılan en az bir uygulama rolü yayımlamalıdır.

Bu izinleri appsettings.json dosyasında belirtiriz. Bu öğreticide, aşağıdaki delege ve uygulama izinlerini kaydettiniz:

  • Temsilci izinleri:ToDoList.Read ve ToDoList.ReadWrite.
  • Uygulama izinleri:ToDoList.Read.All ve ToDoList.ReadWrite.All.

Bir kullanıcı veya istemci uygulaması web API'sini çağırdığında, yalnızca bu kapsamlara veya izinlere sahip istemciler korumalı uç noktaya erişim yetkisine sahip olur.

{
  "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'de kimlik doğrulaması ve yetkilendirme uygulama

Kimlik doğrulamasını ve yetkilendirmeyi yapılandırmak için program.cs dosyasını açın ve içeriğini aşağıdaki kod parçacıklarıyla değiştirin:

Kimlik doğrulama düzeni ekleme

Bu API'de, varsayılan kimlik doğrulama mekanizması olarak JSON Web Belirteci (JWT) Taşıyıcı düzenini kullanırız. JWT taşıyıcı düzenini kaydetmek için AddAuthentication yöntemini kullanın.

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

Uygulamanızın modelini oluşturma

Projenin kök klasöründe Modeller adlı bir klasör oluşturun. Models klasörüne gidin ve adlı ToDo.cs bir dosya oluşturun ve ardından aşağıdaki kodu ekleyin.

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

Yukarıdaki kod ToDo adlı bir model oluşturur. Bu model, uygulamanın yönettiği verileri temsil eder.

Veritabanı bağlamı ekle

Ardından, bir veri modeli için Entity Framework işlevselliğini koordine eden bir veritabanı bağlam sınıfı tanımlayacağız. Bu sınıf, uygulama ve veritabanı arasındaki etkileşimleri yöneten Microsoft.EntityFrameworkCore.DbContext sınıfından devralır. Veritabanı bağlamını eklemek için şu adımları izleyin:

  1. Projenizin kök klasöründe DbContext adlı bir klasör oluşturun.

  2. DbContext klasörüne gidin ve adlı ToDoContext.cs bir dosya oluşturun ve aşağıdaki kodu ekleyin:

    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. Projenizin kök klasöründeki Program.cs dosyasını açın ve aşağıdaki kodla güncelleştirin:

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

Önceki kod örneğinde DB Bağlamını ASP.NET Core uygulama hizmet sağlayıcısında (bağımlılık ekleme kapsayıcısı olarak da bilinir) kapsamlı bir hizmet olarak kaydediyoruz. Ayrıca sınıfını ToDoContext ToDo List API'sinin bellek içi veritabanını kullanacak şekilde yapılandırabilirsiniz.

Denetleyici ayarlama

Denetleyiciler genellikle kaynakları yönetmek için Oluşturma, Okuma, Güncelleştirme ve Silme (CRUD) eylemleri uygular. Bu öğretici, API uç noktalarını korumaya daha fazla odaklandığından, denetleyicide yalnızca iki eylem öğesi uygularız. Tüm To-Do öğelerini almak için Tümünü oku eylemi ve yeni bir To-Do öğesi eklemek için Oluştur eylemi. Projenize denetleyici eklemek için şu adımları izleyin:

  1. Projenizin kök klasörüne gidin ve Denetleyiciler adlı bir klasör oluşturun.

  2. ToDoListController.cs klasörünün içinde adlı bir dosya oluşturun ve aşağıdaki kazan plaka kodunu ekleyin:

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

Denetleyiciye kod ekleme

Bu bölümde, önceki bölümde iskelesi oluşturulmuş denetleyiciye nasıl kod ekleneceği açıklanmaktadır. Burada odak, API'yi oluşturmak değil korumaktır.

  1. Gerekli paketleri içeri aktarın: Paket Microsoft.Identity.Web , belirteç doğrulamasını işleme gibi kimlik doğrulama mantığını kolayca işlememize yardımcı olan MSAL.NET çevresindeki bir sarmalayıcıdır. Uç noktalarımızın yetkilendirme gerektirdiğinden emin olmak için, yerleşik Microsoft.AspNetCore.Authorization paketi kullanırız.

  2. Bu API'nin çağrılması için kullanıcı adına temsilci izinlerini veya istemcinin kullanıcı adına değil kendi adıyla çağırdığı uygulama izinlerini kullanarak çağrılmasını sağladığımız için, çağrının uygulama tarafından kendi adına yapılıp yapılmadığını bilmek önemlidir. Bunu yapmanın en kolay yolu, erişim belirtecinin isteğe bağlı talebi içerip içermediğini idtyp bulmaktır. Bu idtyp talep, API'nin belirtecin uygulama belirteci mi yoksa uygulama + kullanıcı belirteci mi olduğunu belirlemesinin en kolay yoludur. Önerimiz, idtyp isteğe bağlı talebi etkinleştirmenizdir.

    Talep etkin değilse, erişim belirtecinin idtyproles bir uygulama belirteci mi yoksa uygulama + kullanıcı belirteci mi olduğunu belirlemek için ve scp taleplerini kullanabilirsiniz. Microsoft Entra ID tarafından verilen bir erişim token'ı, en az iki hak talebinden birine sahiptir. Kullanıcıya verilen erişim belirteçlerinde scp talebi bulunur. Bir uygulamaya verilen erişim belirteçleri roles talebini içerir. Her iki talebi de içeren erişim belirteçleri yalnızca şu kullanıcılara verilir: scp talebi temsilci izinlerini atamakta, roles talebi ise kullanıcının rolünü atamaktadır. Hiçbir koşulu sağlamayan erişim belirteçleri geçerli sayılmayacaktır.

    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. Yapılan isteğin istenen eylemi gerçekleştirmek için yeterli izinler içerip içermediğini belirleyen bir yardımcı işlev ekleyin. İsteği kendi adına yapan uygulamanın mı yoksa kullanıcının kimliğini doğrulayarak verilen kaynağa sahip olan bir kullanıcı adına arama yapıp yapmadığını denetleyin.

    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. Rotaları korumak için izin tanımlarınızı uygulayın. özniteliğini denetleyici sınıfına [Authorize] ekleyerek API'nizi koruyun. Bu, denetleyici eylemlerinin yalnızca API yetkili bir kimlikle çağrıldığında çağrılabilmesini sağlar. İzin tanımları, bu eylemleri gerçekleştirmek için gereken izin türlerini tanımlar.

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

    GET ve POST uç noktalarına izinler ekleyin. Bunu, Microsoft.Identity.Web.Resource ad alanının parçası olan RequiredScopeOrAppPermission yöntemini kullanarak yapın. Ardından RequiredScopesConfigurationKey ve RequiredAppPermissionsConfigurationKey öznitelikleri aracılığıyla bu yönteme kapsamları ve izinleri geçirirsiniz.

    [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 ara yazılımını denetleyiciyi kullanacak şekilde yapılandırma

Ardından uygulamayı HTTP isteklerini işlemek için denetleyicileri tanıyacak ve kullanacak şekilde yapılandıracağız. program.cs Dosyayı açın ve denetleyici hizmetlerini bağımlılık ekleme kapsayıcısına kaydetmek için aşağıdaki kodu ekleyin.


builder.Services.AddControllers();

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

app.Run();

Yukarıdaki kod parçacığında yöntemi, AddControllers() denetleyici yollarını gelen HTTP isteklerini işlemek için eşlerken MapControllers() gerekli hizmetleri kaydederek uygulamayı denetleyicileri kullanmaya hazırlar.

API'nizi çalıştırma

dotnet runkomutunu kullanarak API'nizin hatasız çalıştığından emin olmak için komutunu çalıştırın. Test sırasında bile HTTPS protokolü kullanmayı planlıyorsanız, NET'in geliştirme sertifikasına güvenmeniz gerekir.

  1. Terminale aşağıdakileri yazarak uygulamayı başlatın:

    dotnet run
    
  2. Terminalde uygulamanın çalıştığını http://localhost:{port} ve istekleri dinlediğini onaylayan aşağıdakine benzer bir çıkış görüntülenmelidir.

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

Web sayfası http://localhost:{host} aşağıdaki görüntüye benzer bir çıktı görüntüler. Bunun nedeni API'nin kimlik doğrulaması olmadan çağrılmasıdır. Yetkili bir arama yapmak için, Sonraki adımlar'e, korumalı bir web API'sine nasıl erişileceğine dair yönergeler için başvurun.

Web sayfası başlatıldığında 401 hatasını gösteren ekran görüntüsü.

Bu API kodunun tam örneği için örnekleri dosyasına bakın.

Sonraki adımlar