Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Eine ASP.NET Core Autorisierungsrichtlinie ist eine benannte Gruppe von mindestens einer Autorisierungsanforderung, die vom Framework ausgewertet wird, um zu entscheiden, ob ein Benutzer auf eine Ressource zugreifen darf.
In diesem Artikel erfahren Sie:
- Erstellen von Anforderungen
- So registrieren und wenden Sie Richtlinien an.
- Autorisierungshandler für die Auswertung einzelner und mehrerer Anforderungen.
- Wie mehrere Anforderungen in einer einzelnen Richtlinie ausgewertet werden.
In der Praxis wird eine Richtlinie mit [Authorize(Policy = "...")] (Razor Komponenten, Seiten und Controllern) oder RequireAuthorization(...) (Endpunkten) angewendet, und das Framework verwendet Handler, um die Anforderungen hinter einer Richtlinie auszuwerten.
IAuthorizationPolicyProvider(Benutzerdefinierte Autorisierungsrichtlinienanbieter in ASP.NET Core Dokumentation) generiert Richtlinien dynamisch, anstatt sie beim App-Start zu registrieren.
Rollenbasierte Autorisierung und anspruchsbasierte Autorisierung verwenden eine Anforderung, einen Anforderungshandler und eine vorkonfigurierte Autorisierungsrichtlinie. Diese Bausteine unterstützen die Erstellung von Autorisierungsauswertungen im Code.
In diesem Artikel werden Razor Komponentenbeispiele verwendet und sich auf Blazor Autorisierungsszenarien für ASP.NET Core 3.1 oder höher konzentriert. Informationen Razor zu Seiten und MVC-Anleitungen, die für alle Versionen von ASP.NET Core gelten, finden Sie in den folgenden Ressourcen nach dem Lesen dieses Artikels:
- Richtlinienbasierte Autorisierung in ASP.NET Core Razor Seiten
- Richtlinienbasierte Autorisierung in ASP.NET Core MVC
Einige Beispiele in diesem Artikel (ASP.NET Core 8.0 oder höher) verwenden primäre Konstruktoren, die in C# 12 (.NET 8) oder höher verfügbar sind. Weitere Informationen finden Sie unter Declare primary constructors for classes and structs (C# documentation tutorial) und Primary constructors (C# Guide).
Anforderungen und Registrierung von Richtlinien
Eine Autorisierungsrichtlinie besteht aus einer oder mehreren Anforderungen, die von einer Richtlinie verwendet werden, um die Autorisierung für den aktuellen Benutzerprinzipal auszuwerten. Eine Anforderung implementiert IAuthorizationRequirement, bei der es sich um eine leere Markerschnittstelle handelt.
Wenn eine Anforderung weder Daten enthält noch Eigenschaften (Parameter) besitzt, fungiert sie als leere Markierung, um einen zugeordneten Autorisierungshandler (IAuthorizationHandler) zur Verarbeitung der Autorisierung auszulösen (wie weiter unten in diesem Artikel ausführlich beschrieben). Da der Handler in diesem Fall vollständig vom HTTP-Kontext, benutzeransprüchen oder Back-End-Daten abhängt, um eine Entscheidung über die Anforderung des Benutzers zu treffen, erfordert die Anforderungsklasse selbst keine internen Daten oder Parameter. Die Anforderung weist nur das Framework an, welche Regel ausgewertet werden soll.
Betrachten Sie beispielsweise die folgende Mindestaltersanforderung (MinimumAgeRequirement), die lediglich als Markerklasse implementiert wird:
public class MinimumAgeRequirement : IAuthorizationRequirement { }
Die vorherige Anforderung wird verwendet, um eine Richtlinie zu erstellen, die bestätigt, dass der Benutzer über ein bestimmtes Alter verfügt, das der Handler überprüft. Ein AuthorizationHandler<MinimumAgeRequirement> prüft AuthorizationHandlerContext.User. Wenn der Benutzer einen Anspruch auf das Geburtsdatum hat, aus dem hervorgeht, dass er älter als ein bestimmtes Alter ist, gilt die Anforderung als erfüllt. Für das Anforderungsobjekt sind in diesem Fall keine Eigenschaften (Parameter) erforderlich. Im nächsten Beispiel wird die vollständige Implementierung einer Mindestaltersanforderung veranschaulicht, die über einen Parameter zum Festlegen des Mindestalters verfügt.
Berücksichtigen Sie die folgende MinimumAgeRequirement Anforderung, die einen einzelnen Parameter, ein Mindestalter, beschreibt, um die Benutzerautorisierung auszuwerten:
using Microsoft.AspNetCore.Authorization;
namespace BlazorWebAppAuthorization.Policies.Requirements;
public class MinimumAgeRequirement(int minimumAge) : IAuthorizationRequirement
{
public int MinimumAge { get; } = minimumAge;
}
using Microsoft.AspNetCore.Authorization;
public class MinimumAgeRequirement : IAuthorizationRequirement
{
public MinimumAgeRequirement(int minimumAge) =>
MinimumAge = minimumAge;
public int MinimumAge { get; }
}
using Microsoft.AspNetCore.Authorization;
public class MinimumAgeRequirement : IAuthorizationRequirement
{
public int MinimumAge { get; }
public MinimumAgeRequirement(int minimumAge)
{
MinimumAge = minimumAge;
}
}
Eine Richtlinie wird als Teil der Autorisierungsdienstkonfiguration in der App-Datei Program durch Aufrufen AuthorizationBuilder.AddPolicyregistriert. Im folgenden Beispiel wird eine AtLeast21 Richtlinie mit einer einzigen Anforderung eines Mindestalters erstellt und das Mindestalter auf 21 Jahre festgelegt.
builder.Services.AddAuthorizationBuilder()
.AddPolicy("AtLeast21", policy =>
policy.Requirements.Add(new MinimumAgeRequirement(21)));
Eine Richtlinie wird als Teil der Autorisierungsdienstkonfiguration in der App-Datei Program durch Aufrufen AuthorizationBuilder.AddPolicyregistriert. Im folgenden Beispiel wird eine AtLeast21 Richtlinie mit einer einzigen Anforderung eines Mindestalters erstellt und das Mindestalter auf 21 Jahre festgelegt:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AtLeast21", policy =>
policy.Requirements.Add(new MinimumAgeRequirement(21)));
});
Eine Richtlinie wird als Teil der Autorisierungsdienstkonfiguration in Startup.ConfigureServices (Startup.cs) durch Aufrufen AuthorizationBuilder.AddPolicyregistriert. Im folgenden Beispiel wird eine AtLeast21 Richtlinie mit einer einzigen Anforderung eines Mindestalters erstellt und das Mindestalter auf 21 Jahre festgelegt:
services.AddAuthorization(options =>
{
options.AddPolicy("AtLeast21", policy =>
policy.Requirements.Add(new MinimumAgeRequirement(21)));
});
Wenn eine Autorisierungsrichtlinie mehrere Autorisierungsanforderungen enthält, müssen alle Anforderungen erfüllt sein, damit die Richtlinie erfolgreich ausgewertet wird. Mit anderen Worten, mehrere Autorisierungsanforderungen, die einer einzigen Autorisierungsrichtlinie hinzugefügt wurden, werden auf UND-Basis behandelt.
Anwenden von Richtlinien auf Razor Komponenten
Anwenden von Richtlinien auf Razor Komponenten mithilfe des [Authorize] Attributs mit dem Richtliniennamen:
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "CustomerServiceMember")]
Wenn mehrere Richtlinien angewendet werden, müssen alle Richtlinien erfüllt sein, bevor der Zugriff gewährt wird:
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "CustomerServiceMember")]
@attribute [Authorize(Policy = "HumanResourcesMember")]
Anwenden von Richtlinien auf Endpunkte
Sie wenden Richtlinien auf Endpunkte an, indem Sie RequireAuthorization mit dem Richtliniennamen verwenden. Beispiel:
app.MapGet("/helloworld", () => "Hello World!")
.RequireAuthorization("AtLeast21");
Richtlinien in MVC-Apps und Razor Pages-Apps anwenden
Anleitungen zum Anwenden von Richtlinien in Razor Seiten und MVC-Apps finden Sie in den folgenden Ressourcen:
- Richtlinienbasierte Autorisierung in ASP.NET Core Razor Seiten
- Richtlinienbasierte Autorisierung in ASP.NET Core MVC
Autorisierungsdienstschnittstelle (IAuthorizationService)
IAuthorizationService ist in erster Linie dafür verantwortlich, zu bestimmen, ob die Autorisierung erfolgreich ist, wenn eine IAuthorizationService.AuthorizeAsync Überladung aufgerufen wird:
-
AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements): Überprüft, ob ein Benutzer einen bestimmten Satz von Autorisierungsanforderungen für eine angegebene Ressource erfüllt. -
AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName): Überprüft, ob ein Benutzer eine bestimmte Autorisierungsrichtlinie für eine angegebene Ressource erfüllt.
Wenn eine Ressource für die Richtlinienauswertung nicht erforderlich ist, wird null als Ressource übergeben.
Die vorangehenden Methoden geben ein AuthorizationResult zurück, das in ein Task eingebettet ist.
Jeder IAuthorizationHandler ist dafür verantwortlich, zu prüfen, ob die Anforderungen über IAuthorizationHandler.HandleAsync erfüllt sind. Die AuthorizationHandlerContext Klasse enthält die autorisierungsinformationen, die von der IAuthorizationHandler Implementierung verwendet werden. IAuthorizationRequirement ist eine Markerschnittstelle ohne Methoden, die als Mechanismus zum Nachverfolgen der Erfolgreichkeit der Autorisierung dienen. Wenn AuthorizationHandlerContext.Succeed mit IAuthorizationRequirement aufgerufen wird, ist die Richtlinie erfüllt:
context.Succeed(requirement);
Autorisierungshandler
Autorisierungshandler sind für die Auswertung der Eigenschaften einer Anforderung verantwortlich. Der Autorisierungshandler wertet die Anforderungen anhand einer bereitgestellten AuthorizationHandlerContext aus, um festzustellen, ob Zugriff zulässig ist.
Eine Anforderung kann über mehrere Handler verfügen. Ein Handler kann erben AuthorizationHandler<TRequirement>, wobei TRequirement es sich um die Anforderung zum Behandeln handelt. Alternativ kann ein Handler IAuthorizationHandler auch direkt implementieren, um mehrere Anforderungstypen zu verarbeiten.
Verwenden Sie einen Handler für eine Anforderung
Das folgende Beispiel zeigt eine 1:1-Beziehung, in der ein Mindestalter-Handler eine einzelne Anforderung behandelt:
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using BlazorWebAppAuthorization.Policies.Requirements;
namespace BlazorWebAppAuthorization.Policies.Handlers;
public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context, MinimumAgeRequirement requirement)
{
var dateOfBirthClaim =
context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth);
if (dateOfBirthClaim is null)
{
return Task.CompletedTask;
}
var dateOfBirth = Convert.ToDateTime(dateOfBirthClaim.Value);
var calculatedAge = DateTime.Today.Year - dateOfBirth.Year;
if (dateOfBirth > DateTime.Today.AddYears(-calculatedAge))
{
calculatedAge--;
}
if (calculatedAge >= requirement.MinimumAge)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context, MinimumAgeRequirement requirement)
{
var dateOfBirthClaim =
context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth);
if (dateOfBirthClaim is null)
{
return Task.CompletedTask;
}
var dateOfBirth = Convert.ToDateTime(dateOfBirthClaim.Value);
var calculatedAge = DateTime.Today.Year - dateOfBirth.Year;
if (dateOfBirth > DateTime.Today.AddYears(-calculatedAge))
{
calculatedAge--;
}
if (calculatedAge >= requirement.MinimumAge)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
MinimumAgeRequirement requirement)
{
if (!context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth))
{
// Use the following if targeting a version of
// .NET Framework older than 4.6:
// return Task.FromResult(0);
return Task.CompletedTask;
}
var dateOfBirth = Convert.ToDateTime(
context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth).Value);
var calculatedAge = DateTime.Today.Year - dateOfBirth.Year;
if (dateOfBirth > DateTime.Today.AddYears(-calculatedAge))
{
calculatedAge--;
}
if (calculatedAge >= requirement.MinimumAge)
{
context.Succeed(requirement);
}
// Use the following if targeting a version of
// .NET Framework older than 4.6:
// return Task.FromResult(0);
return Task.CompletedTask;
}
}
Der vorstehende Code ermittelt, ob der aktuelle Benutzerprinzipal einen „Geburtsdatum“-Anspruch besitzt. Es kann keine Autorisierung erfolgen, wenn der Anspruch fehlt. In diesem Fall wird eine abgeschlossene Aufgabe zurückgegeben. Wenn ein Anspruch vorhanden ist, wird das Alter des Benutzers berechnet. Wenn der oder die Benutzer*in das durch die Anforderung definierte Mindestalter hat, gilt die Autorisierung als erfolgreich. Wenn die Autorisierung erfolgreich ist, wird context.Succeed mit der erfüllten Anforderung als einzigem Parameter aufgerufen.
Verwenden eines Handlers für mehrere Anforderungen
Das folgende Beispiel zeigt eine Eins-zu-viele-Beziehung, in der ein Berechtigungs-Handler drei verschiedene Arten von Anforderungen behandeln kann.
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using BlazorWebAppAuthorization.Policies.Requirements;
namespace BlazorWebAppAuthorization.Policies.Handlers;
public class PermissionHandler : IAuthorizationHandler
{
public Task HandleAsync(AuthorizationHandlerContext context)
{
var pendingRequirements = context.PendingRequirements.ToList();
foreach (var requirement in pendingRequirements)
{
if (requirement is ReadPermission)
{
if (IsOwner(context.User, context.Resource)
|| IsSponsor(context.User, context.Resource))
{
context.Succeed(requirement);
}
}
else if (requirement is EditPermission || requirement is DeletePermission)
{
if (IsOwner(context.User, context.Resource))
{
context.Succeed(requirement);
}
}
}
return Task.CompletedTask;
}
private static bool IsOwner(ClaimsPrincipal user, object? resource)
{
// Code omitted for brevity
return true;
}
private static bool IsSponsor(ClaimsPrincipal user, object? resource)
{
// Code omitted for brevity
return true;
}
}
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
public class PermissionHandler : IAuthorizationHandler
{
public Task HandleAsync(AuthorizationHandlerContext context)
{
var pendingRequirements = context.PendingRequirements.ToList();
foreach (var requirement in pendingRequirements)
{
if (requirement is ReadPermission)
{
if (IsOwner(context.User, context.Resource) ||
IsSponsor(context.User, context.Resource))
{
context.Succeed(requirement);
}
}
else if (requirement is EditPermission ||
requirement is DeletePermission)
{
if (IsOwner(context.User, context.Resource))
{
context.Succeed(requirement);
}
}
}
// Use the following if targeting a version of
// .NET Framework older than 4.6:
// return Task.FromResult(0);
return Task.CompletedTask;
}
private bool IsOwner(ClaimsPrincipal user, object resource)
{
// Code omitted for brevity
return true;
}
private bool IsSponsor(ClaimsPrincipal user, object resource)
{
// Code omitted for brevity
return true;
}
}
Der obige Code durchläuft PendingRequirements, eine Eigenschaft, die Anforderungen enthält, die als nicht erfolgreich markiert sind. Für eine ReadPermission-Anforderung muss der Benutzer entweder ein Eigentümer oder ein Sponsor sein, um auf die angeforderte Ressource zuzugreifen. Für eine EditPermission- oder DeletePermission-Anforderung müssen sie Eigentümer sein, um auf die angeforderte Ressource zuzugreifen.
Handlerregistrierung
Registrieren Sie Handler in der Dienstesammlung während der Konfiguration. Im folgenden Beispiel wird ein Handler für das Mindestalter (MinimumAgeHandler) als Singleton-Dienst registriert; ein Handler kann jedoch mit jeder der integrierten Dienstlebensdauern registriert werden:
builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();
services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();
Es ist möglich, eine Anforderung und einen Handler in einer einzelnen Klasse zu bündeln, die sowohl IAuthorizationRequirement als auch IAuthorizationHandler implementiert. Diese Bündelung sorgt für eine enge Kopplung zwischen Handler und Anforderung und wird nur für einfache Anforderungen und Handler empfohlen. Wenn Sie eine Klasse erstellen, die beide Schnittstellen implementiert, entfällt die Notwendigkeit, den Handler im Dienstcontainer zu registrieren, dank der integrierten PassThroughAuthorizationHandler, die es Anforderungen ermöglicht, sich selbst zu behandeln.
Sehen Sie sich die Implementierung der ASP.NET Core-Klasse AssertionRequirement für ein Beispiel an, bei dem es AssertionRequirement sich sowohl um eine Anforderung als auch um den Handler in einer vollständig eigenständigen Klasse handelt. Die AssertionRequirement API des Frameworks ermöglicht es Ihnen, den Zugriff mithilfe von Inline-Lambda-Ausdrücken zu überprüfen, anstatt separate, textbausteine Anforderungs- und Handlerklassen zu schreiben.
Note
Dokumentationslinks zur .NET-Referenzquelle laden in der Regel die Standard-Branch des Repositorys, die die aktuelle Entwicklung der nächsten Version von .NET darstellt. Um ein Tag für ein bestimmtes Release auszuwählen, wählen Sie diesen mit der Dropdownliste Switch branches or tags (Branches oder Tags wechseln) aus. Weitere Informationen finden Sie unter How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Auswählen eines Versionstags von ASP.NET Core-Quellcode (dotnet/AspNetCore.Docs #26205)).
Was sollten Handler zurückgeben?
Die Handle Methode im Handlerbeispiel gibt keinen Wert zurück. Wie wird ein erfolgreicher oder fehlerhafter Status angezeigt?
Ein Handler signalisiert Erfolg, indem er
context.Succeedaufruft und die erfolgreich validierte Anforderung (IAuthorizationRequirement) übergibt.Ein Handler ist nicht erforderlich, um Fehler im Allgemeinen zu behandeln, da andere Handler für dieselbe Anforderung möglicherweise erfolgreich sind.
Rufen Sie
context.Failauf, um das Scheitern zu garantieren, selbst wenn andere Anforderungshandler erfolgreich sind.
Wenn ein Handler context.Succeed oder context.Fail aufruft, werden weiterhin alle anderen Handler aufgerufen. Dies ermöglicht, dass Anforderungen Nebenwirkungen wie z. B. Protokollierung verursachen, die auch dann stattfinden, wenn ein anderer Handler eine Anforderung erfolgreich validiert oder bei ihr fehlschlägt. Wenn auf false eingestellt, überspringt die InvokeHandlersAfterFailure-Eigenschaft die Ausführung von Handlern, wenn context.Fail aufgerufen wird.
InvokeHandlersAfterFailure ist standardmäßig auf true festgelegt, sodass alle Handler aufgerufen werden.
Note
Autorisierungshandler werden auch dann aufgerufen, wenn die Authentifizierung fehlschlägt. Außerdem können Handler in beliebiger Reihenfolge ausgeführt werden. Dies hängt daher nicht von der Reihenfolge der aufrufenden Handler ab.
Wann sollte ich mehrere Handler für eine Anforderung verwenden?
In Fällen, in denen die Auswertung auf OR-Basis erfolgen soll, implementieren Sie mehrere Handler für eine einzelne Anforderung. Nehmen Wir beispielsweise an, dass die Contoso Corporation Türen hat, die nur mit Schlüsselkarten geöffnet sind. Wenn Sie Ihre Schlüsselkarte zu Hause verlassen, druckt der Empfangsist einen temporären Aufkleber und öffnet die Tür für Sie. In diesem Szenario hat die App eine einzige Anforderung, aber mehrere Handler, die jeweils eine einzelne Anforderung untersuchen.
In den folgenden Beispielimplementierungen:
-
BuildingEntryRequirementist die Voraussetzung für den Gebäudezutritt. -
BadgeEntryHandler(die Person verfügt über einen Ausweis) undTemporaryStickerHandler(die Person hat einen temporären Aufkleber) sind separate Handler, die jeweils genau eine Bedingung prüfen.
BuildingEntryRequirement.cs:
using Microsoft.AspNetCore.Authorization;
namespace BlazorWebAppAuthorization.Policies.Requirements;
public class BuildingEntryRequirement : IAuthorizationRequirement { }
BadgeEntryHandler.cs:
using Microsoft.AspNetCore.Authorization;
using BlazorWebAppAuthorization.Policies.Requirements;
namespace BlazorWebAppAuthorization.Policies.Handlers;
public class BadgeEntryHandler : AuthorizationHandler<BuildingEntryRequirement>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context, BuildingEntryRequirement requirement)
{
if (context.User.HasClaim(c => c.Type == "BadgeId"))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
TemporaryStickerHandler.cs:
using Microsoft.AspNetCore.Authorization;
using BlazorWebAppAuthorization.Policies.Requirements;
namespace BlazorWebAppAuthorization.Policies.Handlers;
public class TemporaryStickerHandler : AuthorizationHandler<BuildingEntryRequirement>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context, BuildingEntryRequirement requirement)
{
if (context.User.HasClaim(c =>
c.Type == "TemporaryBadgeId" &&
c.Issuer == "https://contososecurity"))
{
// Code to check expiration date omitted for brevity.
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
BuildingEntryRequirement.cs:
using Microsoft.AspNetCore.Authorization;
public class BuildingEntryRequirement : IAuthorizationRequirement
{
}
BadgeEntryHandler.cs:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
public class BadgeEntryHandler : AuthorizationHandler<BuildingEntryRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
BuildingEntryRequirement requirement)
{
if (context.User.HasClaim(c =>
c.Type == "BadgeId" &&
c.Issuer == "https://contososecurity"))
{
context.Succeed(requirement);
}
// Use the following if targeting a version of
// .NET Framework older than 4.6:
// return Task.FromResult(0);
return Task.CompletedTask;
}
}
TemporaryStickerHandler.cs:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
public class TemporaryStickerHandler : AuthorizationHandler<BuildingEntryRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
BuildingEntryRequirement requirement)
{
if (context.User.HasClaim(c =>
c.Type == "TemporaryBadgeId" &&
c.Issuer == "https://contososecurity"))
{
// We'd also check the expiration date on the sticker.
context.Succeed(requirement);
}
// Use the following if targeting a version of
// .NET Framework older than 4.6:
// return Task.FromResult(0);
return Task.CompletedTask;
}
}
Stellen Sie sicher, dass beide Handler registriert sind. Wenn bei der Auswertung von BuildingEntryRequirement durch eine Richtlinie einer der beiden Handler erfolgreich ist, ist die Richtlinienauswertung erfolgreich.
Zum Erfüllen einer Richtlinie Func verwenden
Es gibt Situationen, in denen die Erfüllung einer Richtlinie einfach im Code mit einem Func<AuthorizationHandlerContext, bool> Stellvertreter ausgedrückt werden kann, wenn eine Richtlinie mit dem RequireAssertion Richtlinien-Generator konfiguriert wird. Beispielsweise kann der vorherige BadgeEntryHandler Code wie folgt umgeschrieben werden:
options.AddPolicy("AtLeast21", policy =>
policy.Requirements.Add(new MinimumAgeRequirement(21)));
(c.Type == "BadgeId" || c.Type == "TemporaryBadgeId")
&& c.Issuer == "https://contososecurity")));
});
// <snippet_minimumAgeHandlerRegistration>
services.AddAuthorization(options =>
{
options.AddPolicy("BadgeEntry", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c =>
(c.Type == "BadgeId" ||
c.Type == "TemporaryBadgeId") &&
c.Issuer == "https://microsoftsecurity")));
});
Globale Benutzerauthentifizierung erforderlich
Informationen zum Anfordern der Authentifizierung für alle App-Benutzer finden Sie unter Erstellen einer ASP.NET Core-App mit durch Autorisierung geschützten Benutzerdaten.
Autorisierung über ein externes Dienstbeispiel
Die Autorisierung über ein externes Dienstbeispiel (dotnet/AspNetCore.Docs.Samples GitHub Repository) zeigt, wie zusätzliche Autorisierungsanforderungen mit einem externen Autorisierungsdienst implementiert werden. Das Projekt der Contoso.API Lösung wird durch Microsoft Entra ID gesichert. Eine zusätzliche Autorisierungsprüfung des Contoso.Security.API-Projekts gibt einen Rückgabewert zurück, der beschreibt, ob die Contoso.API-Client-App die GetWeather-API aufrufen kann.
Das Beispiel konfigurieren
Die folgende Demonstration basiert auf der Verwendung von NSwag (Swagger/OpenAPI) oder cURL in einer Befehlsshell.
Legen Sie im Contoso.Security.API Projekt den AllowedClients Platzhalter ({CLIENT ID}) auf einen beliebigen Test-GUID-Wert fest (z. B 00001111-aaaa-2222-bbbb-3333cccc4444. ):
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"AllowedClients": [
"{CLIENT ID (FOR THE CLIENT CALLING CONTOSO.API)}"
]
}
Verwenden Sie in einer Befehlsshell, die für das Contoso.API-Projekt geöffnet ist, dotnet user-jwts, um ein Zugriffstoken mit einem appid-Claim für die ID der Client-App zu generieren, die im vorherigen Schritt erstellt wurde (z. B. 00001111-aaaa-2222-bbbb-3333cccc4444).
dotnet user-jwts create --claim appid={GUID}
Beispiel:
dotnet user-jwts create --claim appid=00001111-aaaa-2222-bbbb-3333cccc4444
Die Ausgabe erzeugt ein Token nach „Token:“ in der Befehlsshell:
New JWT saved with ID '{JWT ID}'.
Name: {USER}
Custom Claims: [appid=00001111-aaaa-2222-bbbb-3333cccc4444]
Token: {TOKEN}
Merken Sie sich den Wert des Tokens (wobei der {TOKEN} Platzhalter in der vorherigen Ausgabe angezeigt wird), damit Sie es später verwenden können.
Sie können das Token in einem Onlinedecoder JWT decodieren, z jwt.ms . B. um den Inhalt anzuzeigen, der anzeigt, dass es einen appid Anspruch mit der ID der Client-App enthält:
{
"alg": "HS256",
"typ": "JWT"
}.{
"unique_name": "{USER}",
"sub": "{USER}",
"jti": "14ed7729",
"appid": "{CLIENT ID}",
"aud": [
"https://localhost:7250",
"http://localhost:7251"
],
"nbf": 1780660887,
"exp": 1788609687,
"iat": 1780660888,
"iss": "dotnet-user-jwts"
}.[Signature]
Führen Sie den Befehl erneut mit einem falschen Client-ID -Wert (appid) aus:
dotnet user-jwts create --claim appid=aaaabbbb-0000-cccc-1111-dddd2222eeee
Legen Sie den Wert des zweiten Tokens beiseite.
Starten Sie sowohl die Projekte Contoso.API und Contoso.Security.API in Visual Studio als auch mit dem Befehl dotnet watch in einer Befehlsshell:
dotnet watch
Wählen Sie auf der Benutzeroberfläche von Swagger des Contoso.API Projekts (https://localhost:7250/swagger/index.html) die Schaltfläche "Autorisieren" aus.
Geben Sie im Fenster "Verfügbare Autorisierungen: Bearer Fenster" das Zugriffstoken ein. Wählen Sie die Schaltfläche Autorisieren aus. Schließen Sie das Fenster "Verfügbare Autorisierungen ".
Wählen Sie unter default die Schaltfläche Get für den Endpunkt /WeatherForecast aus. Wählen Sie die Schaltfläche "Ausprobieren" aus . Wählen Sie die Schaltfläche "Ausführen" aus .
Die Ausgabe unter Antworten>Serverantwort>Antworttext zeigt die vom Contoso.API-Projekt zurückgegebene JSON-Wettervorhersage an.
Führen Sie dieselben Schritte mit dem Zugriffstoken aus, das mit einer ungültigen Client-App-ID generiert wurde. Die Antwort ist 403 - Verboten.