Rollenbasierte Autorisierung in ASP.NET Core

Beim Erstellen einer Identität kann diese einer oder mehreren Rollen angehören. Beispielsweise kann Tracy den Rollen Administrator und User angehören, während Scott nur der Rolle User angehört. Wie diese Rollen erstellt und verwaltet werden, hängt vom Sicherungsspeicher des Autorisierungsprozesses ab. Rollen werden den Entwickelnden über die IsInRole-Methode für die ClaimsPrincipal-Klasse verfügbar gemacht. AddRoles muss Rollendiensten hinzugefügt werden.

Obwohl Rollen Ansprüche sind, sind nicht alle Ansprüche auch Rollen. Abhängig vom Identitätsaussteller kann eine Rolle eine Sammlung von Benutzer*innen sein, die Ansprüche für Gruppenmitglieder anwenden können, sowie ein tatsächlicher Anspruch auf eine Identität. Ansprüche sollen jedoch Informationen zu einzelnen Benutzer*innen sein. Die Verwendung von Rollen zum Hinzufügen von Ansprüchen zu einem/einer Benutzer*in kann die Grenze zwischen den Benutzer*innen und ihren individuellen Ansprüchen verwischen. Dies ist der Grund, warum die SPA-Vorlagen nicht auf Rollen ausgelegt sind. Darüber hinaus kann die Verbreitung von Rollen in Organisationen, die von einem lokalen Legacysystem migrieren, im Lauf der Jahre dazu führen, dass ein Rollenanspruch für Token, die von SPAs verwendet werden, möglicherweise zu groß ist. Informationen zum Sichern von SPAs finden Sie unter Verwenden Identity zum Sichern eines Web-API-Back-Ends für SPAs.

Hinzufügen von Rollendiensten in Identity

Registrieren Sie rollenbasierte Autorisierungsdienste in Program.cs, indem Sie AddRoles mit dem Rollentyp in der Identity-Konfiguration der App aufrufen. Der Rollentyp im folgenden Beispiel lautet IdentityRole:

builder.Services.AddDefaultIdentity<IdentityUser>( ... )
    .AddRoles<IdentityRole>()
    ...

Hinzufügen von Rollenüberprüfungen

Für rollenbasierte Autorisierungsüberprüfungen gilt Folgendes:

  • Sie sind deklarativ und geben Rollen an, deren Mitglied der/die aktuelle Benutzer*in sein muss, um auf die angeforderte Ressource zugreifen zu können.
  • Sie werden auf Razor Pages, Controller oder Aktionen innerhalb eines Controllers angewandt.
  • Sie können nicht auf Ebene der Razor-Seitenhandlers angewandt werden, sondern muss auf die Seite angewandt werden.

Der folgende Code beschränkt beispielsweise den Zugriff auf alle Aktionen für den AdministrationController auf Benutzer*innen, die Mitglieder der Rolle Administrator sind:

[Authorize(Roles = "Administrator")]
public class AdministrationController : Controller
{
    public IActionResult Index() =>
        Content("Administrator");
}

Mehrere Rollen können als eine durch Trennzeichen getrennte Liste angegeben werden:

[Authorize(Roles = "HRManager,Finance")]
public class SalaryController : Controller
{
    public IActionResult Payslip() =>
                    Content("HRManager || Finance");
}

Auf den SalaryController können nur Benutzer*innen zugreifen, die Mitglieder der Rolle HRManageroder der Rolle Finance sind.

Werden mehrere Attribute angewandt, müssen die zugreifenden Benutzer*innen Mitglieder aller angegebenen Rollen sein. Im folgenden Beispiel muss ein/e Benutzer*in Mitglied sowohl der Rolle PowerUserals auch der Rolle ControlPanelUser sein:

[Authorize(Roles = "PowerUser")]
[Authorize(Roles = "ControlPanelUser")]
public class ControlPanelController : Controller
{
    public IActionResult Index() =>
        Content("PowerUser && ControlPanelUser");
}

Der Zugriff auf eine Aktion kann durch das Anwenden zusätzlicher Rollenautorisierungsattribute auf Aktionsebene eingeschränkt werden:

[Authorize(Roles = "Administrator, PowerUser")]
public class ControlAllPanelController : Controller
{
    public IActionResult SetTime() =>
        Content("Administrator || PowerUser");

    [Authorize(Roles = "Administrator")]
    public IActionResult ShutDown() =>
        Content("Administrator only");
}

Im vorstehenden Controller ControlAllPanelController gilt Folgendes:

  • Mitglieder der Rolle Administrator oder der Rolle PowerUser können auf den Controller und die Aktion SetTime zugreifen.
  • Nur Mitglieder der Rolle Administrator können auf die Aktion ShutDown zugreifen.

Ein Controller kann gesperrt sein, jedoch anonymen, nicht authentifizierten Zugriff auf einzelne Aktionen zulassen:

[Authorize]
public class Control3PanelController : Controller
{
    public IActionResult SetTime() =>
        Content("[Authorize]");

    [AllowAnonymous]
    public IActionResult Login() =>
        Content("[AllowAnonymous]");
}

Für Razor Pages kann [Authorize] durch eine der folgenden Methoden angewandt werden:

[Authorize(Policy = "RequireAdministratorRole")]
public class UpdateModel : PageModel
{
    public IActionResult OnPost() =>
         Content("OnPost RequireAdministratorRole");
}

Wichtig

Filterattribute einschließlich AuthorizeAttribute können nur auf PageModel angewandt werden und nicht auf bestimmte Seitenhandlermethoden.

Richtlinienbasierte Rollenüberprüfungen

Rollenanforderungen können auch mithilfe der Richtliniensyntax ausgedrückt werden, indem Entwickelnde eine Richtlinie beim Anwendungsstart als Teil der Autorisierungsdienstkonfiguration registrieren. Dies geschieht in der Regel in der Datei Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("RequireAdministratorRole",
         policy => policy.RequireRole("Administrator"));
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

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

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Richtlinien werden mithilfe der Policy-Eigenschaft auf das [Authorize]-Attribut angewandt:

[Authorize(Policy = "RequireAdministratorRole")]
public IActionResult Shutdown()
{
    return View();
}

Sie können mehrere zulässige Rollen in einer Anforderung als Parameter für die RequireRole-Methode angeben:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("ElevatedRights", policy =>
          policy.RequireRole("Administrator", "PowerUser", "BackupAdministrator"));
});

var app = builder.Build();

Der vorstehende Code autorisiert Benutzer*innen, die den Rollen Administrator, PowerUser oder BackupAdministrator angehören.

Beim Erstellen einer Identität kann diese einer oder mehreren Rollen angehören. Beispielsweise kann Tracy den Rollen „Administrator“ und „Benutzer“ angehören, während Scott nur der Rolle „Benutzer“ angehört. Wie diese Rollen erstellt und verwaltet werden, hängt vom Sicherungsspeicher des Autorisierungsprozesses ab. Rollen werden den Entwickelnden über die IsInRole-Methode für die ClaimsPrincipal-Klasse verfügbar gemacht.

Es wird empfohlen, Rollen nicht als Ansprüche zu verwenden, sondern stattdessen Ansprüche zu nutzen. Wenn Sie Single Page Apps (SPAs) verwenden, lesen Sie den Abschnitt Verwenden Identity, um ein Web-API-Backend für SPAs zu sichern.

Hinzufügen von Rollenüberprüfungen

Für rollenbasierte Autorisierungsüberprüfungen gilt Folgendes:

  • Sie sind deklarativ.
  • werden auf Razor Pages, Controller oder Aktionen innerhalb eines Controllers angewandt.
  • Sie können nicht auf Ebene der Razor-Seitenhandlers angewandt werden, sondern muss auf die Seite angewandt werden.

Rollenbasierte Autorisierungsüberprüfungen geben an, in welchen Rollen der/die aktuelle Benutzer*in Mitglied sein muss, um auf die angeforderte Ressource zugreifen zu können.

Der folgende Code beschränkt beispielsweise den Zugriff auf alle Aktionen für den AdministrationController auf Benutzer*innen, die Mitglieder der Rolle Administrator sind:

[Authorize(Roles = "Administrator")]
public class AdministrationController : Controller
{
    public IActionResult Index() =>
        Content("Administrator");
}

Mehrere Rollen können als eine durch Trennzeichen getrennte Liste angegeben werden:

[Authorize(Roles = "HRManager,Finance")]
public class SalaryController : Controller
{
    public IActionResult Payslip() =>
                    Content("HRManager || Finance");
}

Auf den Controller SalaryController können nur Benutzer*innen zugreifen, die Mitglieder der Rolle HRManageroder der Rolle Finance sind.

Wenn Sie mehrere Attribute anwenden, müssen die zugreifenden Benutzer*innen Mitglieder aller angegebenen Rollen sein. Im folgenden Beispiel muss ein/e Benutzer*in Mitglied sowohl der Rolle PowerUser als auch der Rolle ControlPanelUser sein:

[Authorize(Roles = "PowerUser")]
[Authorize(Roles = "ControlPanelUser")]
public class ControlPanelController : Controller
{
    public IActionResult Index() =>
        Content("PowerUser && ControlPanelUser");
}

Sie können den Zugriff weiter einschränken, indem Sie zusätzliche Rollenautorisierungsattribute auf Aktionsebene anwenden:

[Authorize(Roles = "Administrator, PowerUser")]
public class ControlAllPanelController : Controller
{
    public IActionResult SetTime() =>
        Content("Administrator || PowerUser");

    [Authorize(Roles = "Administrator")]
    public IActionResult ShutDown() =>
        Content("Administrator only");
}

Wenn mehrere Attribute auf Controller- und Aktionsebene angewandt werden, müssen alle Attribute die Anforderungen bestehen, bevor der Zugriff gewährt wird:

[Authorize(Roles = "Administrator")]
public class ControlAllPanelController2 : Controller
{
    public IActionResult SetTime() =>
        Content("Administrator only");

    [Authorize(Roles = "PowerUser")]
    public IActionResult ShutDown() =>
        Content("Administrator && PowerUser");
}

Im vorstehenden Controller ControlAllPanelController gilt Folgendes:

  • Mitglieder der Rolle Administrator oder der Rolle PowerUser können auf den Controller und die Aktion SetTime zugreifen.
  • Nur Mitglieder der Rolle Administrator können auf die Aktion ShutDown zugreifen.

Sie können einen Controller auch sperren, jedoch anonymen, nicht authentifizierten Zugriff auf einzelne Aktionen zulassen.

[Authorize]
public class Control3PanelController : Controller
{
    public IActionResult SetTime() =>
        Content("[Authorize]");

    [AllowAnonymous]
    public IActionResult Login() =>
        Content("[AllowAnonymous]");
}

Für Razor Pages kann [Authorize] durch eine der folgenden Methoden angewandt werden:

[Authorize(Policy = "RequireAdministratorRole")]
public class UpdateModel : PageModel
{
    public ActionResult OnPost()
    {
    }
}

Wichtig

Filterattribute einschließlich AuthorizeAttribute können nur auf PageModel angewandt werden und nicht auf bestimmte Seitenhandlermethoden.

Richtlinienbasierte Rollenüberprüfungen

Rollenanforderungen können auch mithilfe der neuen Richtliniensyntax ausgedrückt werden, indem Entwickelnde eine Richtlinie beim Start als Teil der Autorisierungsdienstkonfiguration registrieren. Dies tritt in der Regel in ConfigureServices() in der Datei Startup.cs auf.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();

    services.AddAuthorization(options =>
    {
        options.AddPolicy("RequireAdministratorRole",
             policy => policy.RequireRole("Administrator"));
    });
}

Richtlinien werden mithilfe der Policy-Eigenschaft auf das [Authorize]-Attribut angewandt:

[Authorize(Policy = "RequireAdministratorRole")]
public IActionResult Shutdown()
{
    return View();
}

Sie können auf Wunsch mehrere zulässige Rollen in einer Anforderung als Parameter für die RequireRole-Methode angeben:

options.AddPolicy("ElevatedRights", policy =>
                  policy.RequireRole("Administrator", "PowerUser", "BackupAdministrator"));

In diesem Beispiel werden Benutzer*innen autorisiert, die den Rollen Administrator, PowerUser oder BackupAdministrator angehören.

Hinzufügen von Rollendiensten in Identity

Fügen Sie AddRoles an, um Rollendienste hinzuzufügen:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>()
        .AddRoles<IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddControllersWithViews();
    services.AddRazorPages();
}