Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Une stratégie d’autorisation ASP.NET Core est un ensemble nommé d’une ou plusieurs exigences d’autorisation que l’infrastructure évalue pour déterminer si un utilisateur est autorisé à accéder à une ressource.
Cet article explique :
- Comment créer des exigences.
- Comment inscrire et appliquer des stratégies.
- Gestionnaires d’autorisation pour l’évaluation des exigences uniques et multiples.
- Comment plusieurs exigences dans une stratégie unique sont évaluées.
Dans la pratique, une stratégie est appliquée à [Authorize(Policy = "...")] (Razor composants, pages et contrôleurs) ou à RequireAuthorization(...) (points de terminaison), et l’infrastructure utilise des gestionnaires pour évaluer les exigences associées à une stratégie.
IAuthorizationPolicyProvider(Les fournisseurs de stratégies d’autorisation personnalisées dans ASP.NET Core documentation) génèrent dynamiquement des stratégies au lieu de les inscrire au démarrage de l’application.
L’autorisation basée sur les rôles et l’autorisation basée sur les revendications utilisent une exigence, un gestionnaire de conditions requises et une stratégie d’autorisation préconfigurée. Ces blocs de construction prennent en charge l’expression des évaluations d’autorisation dans le code.
Cet article utilise des exemples de composants Razor et se concentre sur les scénarios d’autorisation Blazor pour ASP.NET Core 3.1 ou version ultérieure. Pour Razor obtenir des conseils sur les pages et MVC qui s’appliquent à toutes les versions de ASP.NET Core, consultez les ressources suivantes après avoir lu cet article :
- Autorisation basée sur des stratégies dans ASP.NET Core Razor Pages
- Autorisation basée sur une stratégie dans ASP.NET Core MVC
Certains exemples de cet article (ASP.NET Core 8.0 ou version ultérieure) utilisent des constructeurs principaux, disponibles en C# 12 (.NET 8) ou version ultérieure. Pour plus d’informations, consultez Déclarer des constructeurs principaux pour les classes et les structs (didacticiel de documentation C#) et les constructeurs principaux (Guide C#).
Exigences et enregistrement de stratégie
Une stratégie d’autorisation se compose d’une ou plusieurs exigences, utilisées pour évaluer l’autorisation du principal utilisateur actuel. Une exigence implémente IAuthorizationRequirement, qui est une interface de marqueur vide.
Lorsqu’une exigence ne contient pas de données ni possède des propriétés (paramètres), elle agit comme un marqueur vide pour déclencher un gestionnaire d’autorisation associé (IAuthorizationHandler) pour le traitement de l’autorisation (décrite en détail plus loin dans cet article). Étant donné que le gestionnaire s’appuie entièrement sur le contexte HTTP, les revendications utilisateur ou les données back-end pour prendre une décision sur l’utilisateur répondant à l’exigence, la classe d’exigence elle-même ne nécessite pas de données ou de paramètres internes. L’exigence indique uniquement au framework quelle règle évaluer.
Par exemple, considérez l’exigence d’âge minimale suivante (MinimumAgeRequirement), qui est implémentée simplement en tant que classe de marqueur :
public class MinimumAgeRequirement : IAuthorizationRequirement { }
L’exigence précédente est utilisée pour créer une stratégie qui confirme que l’utilisateur a plus d’un âge spécifique que le gestionnaire vérifie. Un AuthorizationHandler<MinimumAgeRequirement> inspecte le AuthorizationHandlerContext.User. Si l’utilisateur a une revendication de date de naissance qui indique qu’il a plus d’un certain âge, l’exigence réussit. L’objet d’exigence ne nécessite aucune propriété (paramètres) dans ce cas. L’exemple suivant illustre l’implémentation complète d’une exigence d’âge minimum qui a un paramètre pour définir l’âge minimal.
Tenez compte de l’exigence suivante MinimumAgeRequirement , qui décrit un paramètre unique, un âge minimal, pour évaluer l’autorisation de l’utilisateur :
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;
}
}
Une stratégie est enregistrée dans la configuration du service d’autorisation, dans le fichier Program de l’application, en appelant AuthorizationBuilder.AddPolicy. L’exemple suivant crée une AtLeast21 stratégie avec une exigence unique d’un âge minimal et définit l’âge minimal sur 21 ans.
builder.Services.AddAuthorizationBuilder()
.AddPolicy("AtLeast21", policy =>
policy.Requirements.Add(new MinimumAgeRequirement(21)));
Une stratégie est enregistrée dans la configuration du service d’autorisation, dans le fichier Program de l’application, en appelant AuthorizationBuilder.AddPolicy. L’exemple suivant crée une AtLeast21 stratégie avec une seule exigence d’âge minimal et définit l’âge minimal sur 21 ans :
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AtLeast21", policy =>
policy.Requirements.Add(new MinimumAgeRequirement(21)));
});
Une stratégie est enregistrée dans la configuration du service d’autorisation dans Startup.ConfigureServices (Startup.cs), en appelant AuthorizationBuilder.AddPolicy. L’exemple suivant crée une AtLeast21 stratégie avec une seule exigence d’âge minimal et définit l’âge minimal sur 21 ans :
services.AddAuthorization(options =>
{
options.AddPolicy("AtLeast21", policy =>
policy.Requirements.Add(new MinimumAgeRequirement(21)));
});
Si une stratégie d’autorisation contient plusieurs exigences d’autorisation, toutes les exigences doivent être passées pour que l’évaluation de la stratégie réussisse. En d’autres termes, plusieurs exigences d’autorisation ajoutées à une stratégie d’autorisation unique sont traitées sur une base AND.
Appliquer des stratégies aux Razor composants
Appliquez des stratégies aux composants Razor à l’aide de l’attribut [Authorize] avec le nom de la stratégie :
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "CustomerServiceMember")]
Si plusieurs stratégies sont appliquées, toutes les stratégies doivent passer avant l’octroi de l’accès :
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "CustomerServiceMember")]
@attribute [Authorize(Policy = "HumanResourcesMember")]
Appliquer des stratégies aux points de terminaison
Appliquez des stratégies aux points de terminaison à l'aide de RequireAuthorization avec le nom de la stratégie. Par exemple:
app.MapGet("/helloworld", () => "Hello World!")
.RequireAuthorization("AtLeast21");
Appliquer des stratégies dans les applications MVC et Razor Pages
Pour obtenir des conseils sur l’application de stratégies dans Razor les applications Pages et MVC, consultez les ressources suivantes :
- Autorisation basée sur des stratégies dans ASP.NET Core Razor Pages
- Autorisation basée sur une stratégie dans ASP.NET Core MVC
Interface de service d’autorisation (IAuthorizationService)
IAuthorizationService est principalement chargé de déterminer si l’autorisation est accordée lorsqu’une surcharge de IAuthorizationService.AuthorizeAsync est appelée :
-
AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements): vérifie si un utilisateur répond à un ensemble spécifique d’exigences d’autorisation pour une ressource spécifiée. -
AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName): vérifie si un utilisateur répond à une stratégie d’autorisation spécifique pour une ressource spécifiée.
Si une ressource n’est pas requise pour évaluer la stratégie, null est transmis comme ressource.
Les méthodes précédentes renvoient un AuthorizationResult encapsulé dans un Task.
Chacun d’eux IAuthorizationHandler est chargé de vérifier si les exigences sont remplies via IAuthorizationHandler.HandleAsync. La AuthorizationHandlerContext classe contient les informations d’autorisation utilisées par l’implémentation IAuthorizationHandler . IAuthorizationRequirement est une interface de marqueur sans méthodes qui sert de mécanisme pour le suivi de la réussite de l’autorisation. Quand AuthorizationHandlerContext.Succeed est appelée avec le IAuthorizationRequirement, la stratégie est respectée :
context.Succeed(requirement);
Gestionnaires d’autorisation
Un gestionnaire d’autorisation est responsable de l’évaluation des propriétés d’une exigence. Le gestionnaire d’autorisation évalue les exigences par rapport à un AuthorizationHandlerContext fourni pour déterminer si access est autorisé.
Une exigence peut avoir plusieurs gestionnaires. Un gestionnaire peut hériter de AuthorizationHandler<TRequirement>, où TRequirement est l’exigence à traiter. Un gestionnaire peut également implémenter IAuthorizationHandler directement pour gérer plusieurs types d’exigences.
Utiliser un gestionnaire pour une exigence
L’exemple suivant montre une relation un-à-un dans laquelle un gestionnaire d’âge minimum gère une seule exigence :
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;
}
}
Le code précédent détermine si le principal de l’utilisateur actuel possède une revendication de date de naissance. L'autorisation ne peut pas être accordée lorsque la réclamation est manquante, auquel cas une tâche achevée est retournée. Lorsqu’une revendication est présente, l’âge de l’utilisateur est calculé. Si l’utilisateur répond à l’âge minimal défini par l’exigence, l’autorisation est considérée comme réussie. Lorsque l’autorisation réussit, context.Succeed est appelé avec l’exigence satisfaite comme seul paramètre.
Utiliser un gestionnaire pour plusieurs exigences
L’exemple suivant montre une relation un-à-plusieurs dans laquelle un gestionnaire d’autorisations peut gérer trois types d’exigences différents :
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;
}
}
Le code précédent parcourt PendingRequirements— une propriété contenant des exigences non marquées comme réussies. Pour une condition ReadPermission, l’utilisateur doit être soit un propriétaire, soit un sponsor pour accéder à la ressource demandée. Pour une exigence EditPermission ou DeletePermission, ils doivent être propriétaires pour accéder à la ressource demandée.
Enregistrement du gestionnaire
Inscrivez des gestionnaires dans la collection de services pendant la configuration. L’exemple suivant enregistre un gestionnaire d’âge minimal (MinimumAgeHandler) en tant que service singleton, mais un gestionnaire peut être inscrit à l’aide de l’une des durées de vie de service intégrées :
builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();
services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();
Il est possible de regrouper à la fois une exigence et un gestionnaire dans une classe unique implémentant à la fois IAuthorizationRequirement et IAuthorizationHandler. Ce regroupement crée un couplage étroit entre le gestionnaire et la spécification et est recommandé uniquement pour les exigences et les gestionnaires simples. La création d’une classe qui implémente les deux interfaces supprime la nécessité d’inscrire le gestionnaire dans le conteneur de service en raison de la configuration intégrée PassThroughAuthorizationHandler qui permet aux exigences de gérer elles-mêmes.
Consultez l’implémentation de la classe ASP.NET Core AssertionRequirement pour voir un exemple où AssertionRequirement est à la fois une condition et le gestionnaire dans une classe entièrement autonome. L’API du framework AssertionRequirement vous permet de valider l’accès à l’aide d’expressions lambda en ligne, plutôt que de devoir écrire des classes distinctes d’exigence et de gestionnaire répétitives.
Note
Les liens de documentation vers la source de référence .NET chargent généralement la branche par défaut du référentiel, qui représente le développement actuel pour la prochaine version de .NET. Pour sélectionner une balise pour une version spécifique, utilisez la liste déroulante Échanger les branches ou les balises. Pour plus d’informations, consultez Comment choisir une étiquette de version du code source d'ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Que doit retourner un gestionnaire ?
La Handle méthode de l’exemple de gestionnaire ne retourne aucune valeur. Comment un état de réussite ou d’échec est-il indiqué ?
Un gestionnaire indique la réussite en appelant
context.Succeed, en passant l’exigence validée avec succès (IAuthorizationRequirement).Un gestionnaire n’est pas nécessaire pour gérer les défaillances en général, car d’autres gestionnaires pour la même exigence peuvent réussir.
Pour garantir l'échec, même si d'autres gestionnaires d'exigences réussissent, appelez
context.Fail
Si un gestionnaire appelle context.Succeed ou context.Fail, tous les autres gestionnaires sont toujours appelés. Cela permet aux exigences de produire des effets secondaires, tels que la journalisation, qui se produit même si un autre gestionnaire valide ou échoue correctement sur une exigence. Lorsqu’elle est définie sur false, la InvokeHandlersAfterFailure propriété court-circuite l’exécution des gestionnaires quand context.Fail est appelé.
InvokeHandlersAfterFailure la valeur par défaut est true, auquel cas tous les gestionnaires sont appelés.
Note
Les gestionnaires d’autorisation sont appelés même si l’authentification échoue. En outre, les gestionnaires peuvent s’exécuter dans n’importe quel ordre, donc ne dépendez pas de l’ordre d’appel des gestionnaires.
Pourquoi voudrais-je plusieurs gestionnaires pour une exigence ?
Dans les cas où vous souhaitez que l’évaluation soit sur une base OR, implémentez plusieurs gestionnaires pour une seule exigence. Par exemple, supposons que Contoso Corporation dispose de portes qui s’ouvrent uniquement avec des cartes de clés. Si vous laissez votre carte de clé à la maison, le réceptionniste imprime un autocollant temporaire et ouvre la porte pour vous. Dans ce scénario, l’application a une exigence unique, mais plusieurs gestionnaires, chacun examinant une seule exigence.
Dans les exemples d’implémentations suivants :
-
BuildingEntryRequirementest l’exigence d’accès au bâtiment. -
BadgeEntryHandler(l’individu a un badge) etTemporaryStickerHandler(l’individu a un autocollant temporaire) sont des gestionnaires distincts, chacun examinant une seule exigence.
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;
}
}
Vérifiez que les deux gestionnaires sont inscrits. Si l’un des gestionnaires réussit lorsqu’une stratégie évalue le BuildingEntryRequirement, l’évaluation de la stratégie réussit.
Utiliser un(e) Func pour satisfaire à une stratégie
Il existe des situations où la réalisation d’une stratégie est simple à exprimer dans le code avec un Func<AuthorizationHandlerContext, bool> délégué lors de la configuration d’une stratégie avec le RequireAssertion générateur de stratégies. Par exemple, le précédent BadgeEntryHandler peut être réécrit comme suit :
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")));
});
Exiger une authentification utilisateur globale
Pour plus d’informations sur la façon d’exiger l’authentification pour tous les utilisateurs de l’application, consultez Créer une application ASP.NET Core avec des données utilisateur protégées par autorisation.
Autorisation via un exemple de service externe
L’exemple « Autorisation via un service externe » (dotnet/AspNetCore.Docs.Samples dépôt GitHub) montre comment mettre en œuvre des exigences d’autorisation supplémentaires à l’aide d’un service d’autorisation externe. Le projet de la Contoso.API solution est sécurisé avec Microsoft Entra ID. Une vérification d’autorisation supplémentaire de la Contoso.Security.API project retourne une charge utile décrivant si l’application cliente Contoso.API peut appeler l’API GetWeather.
Configurer l'exemple
La démonstration suivante s’appuie sur l’utilisation de NSwag (Swagger/OpenAPI) ou cURL dans un interpréteur de commandes.
Dans le projet Contoso.Security.API, définissez l’espace réservé AllowedClients ({CLIENT ID}) sur une valeur GUID de test quelconque (par exemple, 00001111-aaaa-2222-bbbb-3333cccc4444):
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"AllowedClients": [
"{CLIENT ID (FOR THE CLIENT CALLING CONTOSO.API)}"
]
}
Dans un interpréteur de commandes ouvert dans le projet Contoso.API, utilisez dotnet user-jwts pour générer un jeton d’accès avec une revendication appid pour l’ID de l’application cliente, créé à l’étape précédente (par exemple, 00001111-aaaa-2222-bbbb-3333cccc4444).
dotnet user-jwts create --claim appid={GUID}
Exemple :
dotnet user-jwts create --claim appid=00001111-aaaa-2222-bbbb-3333cccc4444
La sortie produit un jeton après «Token: » dans l’interpréteur de commandes :
New JWT saved with ID '{JWT ID}'.
Name: {USER}
Custom Claims: [appid=00001111-aaaa-2222-bbbb-3333cccc4444]
Token: {TOKEN}
Mettez de côté la valeur du token (à l’emplacement du paramètre {TOKEN} dans la sortie précédente) pour l’utiliser plus tard.
Vous pouvez décoder le jeton dans un décodeur en ligne JWT , par exemple jwt.ms pour afficher son contenu, révélant qu’il contient une appid revendication avec l’ID de l’application cliente :
{
"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]
Réexécutez la commande avec une valeur d’ID client (appid) incorrecte :
dotnet user-jwts create --claim appid=aaaabbbb-0000-cccc-1111-dddd2222eeee
Mettez la valeur du deuxième jeton de côté.
Démarrez les deux projets Contoso.API et Contoso.Security.API dans Visual Studio ou à l’aide de la commande dotnet watch dans un interpréteur de commandes :
dotnet watch
Dans l’interface utilisateur Swagger du Contoso.API projet (https://localhost:7250/swagger/index.html), sélectionnez le bouton Autoriser .
Dans les autorisations disponibles : Bearer fenêtre, entrez le jeton d’accès. Sélectionnez le bouton Autoriser. Fermez la fenêtre Autorisations disponibles .
Sous Par défaut, sélectionnez le bouton Get pour le point de terminaison /WeatherForecast. Sélectionnez le bouton Essayer. Sélectionnez le bouton Exécuter.
La sortie dans Réponses>Réponse du serveur>Corps de la réponse affiche le JSON des prévisions météorologiques renvoyé par le projet Contoso.API.
Effectuez les mêmes étapes avec le jeton d’accès généré avec un ID d’application client non valide. La réponse est 403 - Interdit.