Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A borítók alatt a szerepköralapú engedélyezés és a jogcímalapú engedélyezés egy követelményt, egy követelménykezelőt és egy előre konfigurált szabályzatot használ. Ezek az építőelemek támogatják az engedélyezési értékelések kódban való kifejezését. Az eredmény egy gazdagabb, újrafelhasználható, tesztelhető engedélyezési struktúra.
Az engedélyezési szabályzatok egy vagy több követelményből állnak. Regisztrálja az engedélyezési szolgáltatás konfigurációjának részeként az alkalmazás fájljában Program.cs :
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AtLeast21", policy =>
policy.Requirements.Add(new MinimumAgeRequirement(21)));
});
Az előző példában létrejön egy "AtLeast21" szabályzat. Egyetlen követelménye van– a minimális életkor, amelyet a követelmény paramétereként ad meg.
IAuthorizationService
Az elsődleges szolgáltatás, amely meghatározza, hogy az engedélyezés sikeres-e:IAuthorizationService
/// <summary>
/// Checks policy based permissions for a user
/// </summary>
public interface IAuthorizationService
{
/// <summary>
/// Checks if a user meets a specific set of requirements for the specified resource
/// </summary>
/// <param name="user">The user to evaluate the requirements against.</param>
/// <param name="resource">
/// An optional resource the policy should be checked with.
/// If a resource is not required for policy evaluation you may pass null as the value
/// </param>
/// <param name="requirements">The requirements to evaluate.</param>
/// <returns>
/// A flag indicating whether authorization has succeeded.
/// This value is <value>true</value> when the user fulfills the policy;
/// otherwise <value>false</value>.
/// </returns>
/// <remarks>
/// Resource is an optional parameter and may be null. Please ensure that you check
/// it is not null before acting upon it.
/// </remarks>
Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource,
IEnumerable<IAuthorizationRequirement> requirements);
/// <summary>
/// Checks if a user meets a specific authorization policy
/// </summary>
/// <param name="user">The user to check the policy against.</param>
/// <param name="resource">
/// An optional resource the policy should be checked with.
/// If a resource is not required for policy evaluation you may pass null as the value
/// </param>
/// <param name="policyName">The name of the policy to check against a specific
/// context.</param>
/// <returns>
/// A flag indicating whether authorization has succeeded.
/// Returns a flag indicating whether the user, and optional resource has fulfilled
/// the policy.
/// <value>true</value> when the policy has been fulfilled;
/// otherwise <value>false</value>.
/// </returns>
/// <remarks>
/// Resource is an optional parameter and may be null. Please ensure that you check
/// it is not null before acting upon it.
/// </remarks>
Task<AuthorizationResult> AuthorizeAsync(
ClaimsPrincipal user, object resource, string policyName);
}
Az előző kód az IAuthorizationService két metódusát emeli ki.
IAuthorizationRequirement metódusok nélküli jelölőszolgáltatás, és az engedélyezés sikerességének nyomon követésére szolgáló mechanizmus.
Mindegyik IAuthorizationHandler felelős annak ellenőrzéséért, hogy teljesülnek-e a követelmények:
/// <summary>
/// Classes implementing this interface are able to make a decision if authorization
/// is allowed.
/// </summary>
public interface IAuthorizationHandler
{
/// <summary>
/// Makes a decision if authorization is allowed.
/// </summary>
/// <param name="context">The authorization information.</param>
Task HandleAsync(AuthorizationHandlerContext context);
}
A AuthorizationHandlerContext kezelő az osztályt használja annak jelzésére, hogy teljesültek-e a követelmények:
context.Succeed(requirement)
Az alábbi kód az engedélyezési szolgáltatás egyszerűsített (megjegyzésekkel ellátott) alapértelmezett implementációját mutatja be:
public async Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user,
object resource, IEnumerable<IAuthorizationRequirement> requirements)
{
// Create a tracking context from the authorization inputs.
var authContext = _contextFactory.CreateContext(requirements, user, resource);
// By default this returns an IEnumerable<IAuthorizationHandler> from DI.
var handlers = await _handlers.GetHandlersAsync(authContext);
// Invoke all handlers.
foreach (var handler in handlers)
{
await handler.HandleAsync(authContext);
}
// Check the context, by default success is when all requirements have been met.
return _evaluator.Evaluate(authContext);
}
Az alábbi kód egy tipikus engedélyezési szolgáltatáskonfigurációt mutat be:
// Add all of your handlers to DI.
builder.Services.AddSingleton<IAuthorizationHandler, MyHandler1>();
// MyHandler2, ...
builder.Services.AddSingleton<IAuthorizationHandler, MyHandlerN>();
// Configure your policies
builder.Services.AddAuthorization(options =>
options.AddPolicy("Something",
policy => policy.RequireClaim("Permission", "CanViewPage", "CanViewAnything")));
Használja IAuthorizationService, [Authorize(Policy = "Something")]vagy RequireAuthorization("Something") engedélyezéshez.
Szabályzatok alkalmazása MVC-vezérlőkre
A Pagest használó Razor alkalmazások esetében lásd a Szabályzatok alkalmazása a Lapokra Razor című szakaszt.
Szabályzatok alkalmazása a vezérlőkre a [Authorize] szabályzatnévvel ellátott attribútum használatával:
[Authorize(Policy = "AtLeast21")]
public class AtLeast21Controller : Controller
{
public IActionResult Index() => View();
}
Ha a vezérlő és a művelet szintjén több szabályzatot is alkalmaz, az összes szabályzatnak át kell mennie a hozzáférés megadása előtt:
[Authorize(Policy = "AtLeast21")]
public class AtLeast21Controller2 : Controller
{
[Authorize(Policy = "IdentificationValidated")]
public IActionResult Index() => View();
}
Szabályzatok alkalmazása lapokra Razor
A Razor Pages lapokra szabályzatok alkalmazása a [Authorize] attribútummal, amely megadja a szabályzat nevét. Például:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace AuthorizationPoliciesSample.Pages;
[Authorize(Policy = "AtLeast21")]
public class AtLeast21Model : PageModel { }
A szabályzatok nem alkalmazhatók az Razor lapkezelő szintjén, azokat az oldalra kell alkalmazni.
A szabályzatok Razor is alkalmazhatók a Pagesre.
Szabályzatok alkalmazása végpontokra
Alkalmazzon szabályzatokat a végpontokra a(z) RequireAuthorization használatával a szabályzat nevével. Például:
app.MapGet("/helloworld", () => "Hello World!")
.RequireAuthorization("AtLeast21");
Requirements
Az engedélyezési követelmény olyan adatparaméterek gyűjteménye, amelyeket egy szabályzat az aktuális felhasználói főszereplő kiértékelésére használhat. Az "AtLeast21" szabályzatban a követelmény egyetlen paraméter – a minimális életkor. A követelmény valósítja meg IAuthorizationRequirement, amely egy üres jelölőinterfész. A paraméteres minimális életkorra vonatkozó követelmény az alábbiak szerint valósítható meg:
using Microsoft.AspNetCore.Authorization;
namespace AuthorizationPoliciesSample.Policies.Requirements;
public class MinimumAgeRequirement : IAuthorizationRequirement
{
public MinimumAgeRequirement(int minimumAge) =>
MinimumAge = minimumAge;
public int MinimumAge { get; }
}
Ha egy engedélyezési szabályzat több engedélyezési követelményeket is tartalmaz, minden követelménynek teljesülnie kell ahhoz, hogy a szabályzat kiértékelése sikeres legyen. Más szóval, az egyetlen engedélyezési szabályzathoz hozzáadott több engedélyezési követelmény kezelése ÉS alapon történik.
Note
Egy követelménynek nem kell adatokkal vagy tulajdonságokkal rendelkeznie.
Engedélyezési kezelők
Egy követelmény tulajdonságainak kiértékeléséért egy engedélyezési kezelő felelős. Az engedélyezési kezelő kiértékeli a követelményeket a megadottak AuthorizationHandlerContext alapján annak megállapításához, hogy engedélyezett-e a hozzáférés.
Egy követelmény több kezelővel is rendelkezhet. A kezelő örökölhet AuthorizationHandler<TRequirement>, ahol TRequirement a kezelendő követelmény. Másik lehetőségként egy kezelő közvetlenül is megvalósíthat IAuthorizationHandler egynél több követelménytípus kezelésére.
Kezelő használata egyetlen követelményhez
Az alábbi példa egy-az-egyhez kapcsolatot mutat be, amelyben egy minimális korhatár-kezelő egyetlen követelményt kezel:
using System.Security.Claims;
using AuthorizationPoliciesSample.Policies.Requirements;
using Microsoft.AspNetCore.Authorization;
namespace AuthorizationPoliciesSample.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 && c.Issuer == "http://contoso.com");
if (dateOfBirthClaim is null)
{
return Task.CompletedTask;
}
var dateOfBirth = Convert.ToDateTime(dateOfBirthClaim.Value);
int calculatedAge = DateTime.Today.Year - dateOfBirth.Year;
if (dateOfBirth > DateTime.Today.AddYears(-calculatedAge))
{
calculatedAge--;
}
if (calculatedAge >= requirement.MinimumAge)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
Az előző kód azt határozza meg, hogy az aktuális felhasználónév rendelkezik-e születési dátummal, amelyet egy ismert és megbízható kibocsátó állított ki. Az engedélyezés nem történhet meg, ha a kérelem hiányzik, ilyenkor visszaad egy befejezett feladatot. Ha egy jogcím jelen van, a rendszer kiszámítja a felhasználó életkorát. Ha a felhasználó megfelel a követelmény által meghatározott minimális életkornak, az engedélyezés sikeresnek minősül. Amikor az engedélyezés sikeres, context.Succeed az egyetlen paraméterként hívja meg az elégedett követelményt.
Kezelő használata több követelményhez
Az alábbi példa egy egy-a-többhöz kapcsolatot mutat be, amelyben egy engedélykezelő három különböző követelménytípust képes kezelni:
using System.Security.Claims;
using AuthorizationPoliciesSample.Policies.Requirements;
using Microsoft.AspNetCore.Authorization;
namespace AuthorizationPoliciesSample.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;
}
}
Az előző kód bejárja a PendingRequirements-t — egy olyan tulajdonságot, amely nem sikeresnek jelölt követelményeket tartalmaz.
ReadPermission Egy követelmény esetében a felhasználónak tulajdonosnak vagy szponzornak kell lennie a kért erőforrás eléréséhez. Egy EditPermission vagy DeletePermission követelmény esetén tulajdonosnak kell lennie ahhoz, hogy hozzáférjen a kért erőforráshoz.
Kezelő regisztrációja
Kezelők regisztrálása a szolgáltatásgyűjteményben a konfiguráció során. Például:
builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();
Az előző kód singletonként regisztrálja a MinimumAgeHandler -t. A kezelők bármelyik beépített szolgáltatási élettartamot felhasználva regisztrálhatók.
Egyetlen osztályba lehet csomagolni mind a követelményt, mind a kezelőt, amely megvalósítja mind a IAuthorizationRequirement, mind a IAuthorizationHandler. Ez a kötegelés szoros kapcsolatot hoz létre a kezelő és a követelmény között, és csak az egyszerű követelmények és kezelők számára ajánlott. Ha mindkét felületet megvalósító osztályt hoz létre, azzal nem kell regisztrálnia a kezelőt a DI-ben, mert a beépített rendszer PassThroughAuthorizationHandler lehetővé teszi a követelmények kezelését.
Tekintse meg az AssertionRequirement osztály implementálását egy jó példáért, ahol a AssertionRequirement követelmény és a kezelő is egy teljesen önálló osztályban található.
Mit kell visszaadnia egy kezelőnek?
Vegye figyelembe, hogy a Handlekezelő példában szereplő metódus nem ad vissza értéket. Hogyan jelzi a sikeres vagy sikertelen állapotot?
A kezelő a sikert úgy jelzi, hogy hívást kezdeményez
context.Succeed(IAuthorizationRequirement requirement), átadva a sikeresen érvényesített követelményt.A kezelőknek általában nem kell kezelnie a hibákat, mivel ugyanazon követelmény más kezelői is sikeresek lehetnek.
A sikertelenség garantálásához, még akkor is, ha más követelménykezelők sikeresek, hívja meg a
context.Fail.
Ha egy kezelő hívásokat kezdeményez context.Succeed , vagy context.Failaz összes többi kezelőt továbbra is meghívja a rendszer. Ez lehetővé teszi, hogy a követelmények olyan mellékhatásokat okoznak, mint a naplózás, amely akkor is megtörténik, ha egy másik kezelő sikeresen érvényesített vagy meghiúsult egy követelményt. Ha be van falseállítva, a InvokeHandlersAfterFailure tulajdonság megszakítja a kezelők végrehajtását, amikor context.Fail meghívják.
InvokeHandlersAfterFailure alapértelmezés szerint true, ilyenkor az összes kezelőt meghívják.
Note
Az engedélyezési kezelőket akkor is meghívja a rendszer, ha a hitelesítés sikertelen. A kezelők bármilyen sorrendben végrehajthatók, ezért ne számítsanak arra, hogy őket egy meghatározott sorrendben hívják meg.
Miért szeretnék több kezelőt egy követelményhez?
Azokban az esetekben, amikor a kiértékelést VAGY alapon szeretné elvégezni, egyetlen követelményhez több kezelőt kell implementálnia. A Microsoft például csak kulcskártyákkal nyitott ajtókkal rendelkezik. Ha otthon hagyja a kulcskártyát, a recepciós kinyomtat egy ideiglenes matricát, és megnyitja az ajtót. Ebben a forgatókönyvben egyetlen követelmény, a BuildingEntry, de több kezelő van, amelyek mindegyike egyetlen követelményt vizsgál.
BuildingEntryRequirement.cs
using Microsoft.AspNetCore.Authorization;
namespace AuthorizationPoliciesSample.Policies.Requirements;
public class BuildingEntryRequirement : IAuthorizationRequirement { }
BadgeEntryHandler.cs
using AuthorizationPoliciesSample.Policies.Requirements;
using Microsoft.AspNetCore.Authorization;
namespace AuthorizationPoliciesSample.Policies.Handlers;
public class BadgeEntryHandler : AuthorizationHandler<BuildingEntryRequirement>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context, BuildingEntryRequirement requirement)
{
if (context.User.HasClaim(
c => c.Type == "BadgeId" && c.Issuer == "https://microsoftsecurity"))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
TemporaryStickerHandler.cs
using AuthorizationPoliciesSample.Policies.Requirements;
using Microsoft.AspNetCore.Authorization;
namespace AuthorizationPoliciesSample.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://microsoftsecurity"))
{
// Code to check expiration date omitted for brevity.
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
Győződjön meg arról, hogy mindkét kezelő regisztrálva van. Ha bármelyik kezelő sikeres lesz, amikor egy szabályzat kiértékeli a BuildingEntryRequirementszabályzatot, a szabályzat kiértékelése sikeres lesz.
Szabályzat teljesítése func használatával
Előfordulhatnak olyan helyzetek, amikor egy szabályzat teljesítése egyszerűen kifejezhető kódban. Az Func<AuthorizationHandlerContext, bool> megadható, amikor egy szabályzatot konfigurálnak a RequireAssertion szabályzatkészítővel.
Az előző BadgeEntryHandler például a következőképpen írható át:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("BadgeEntry", policy =>
policy.RequireAssertion(context => context.User.HasClaim(c =>
(c.Type == "BadgeId" || c.Type == "TemporaryBadgeId")
&& c.Issuer == "https://microsoftsecurity")));
});
MVC-kérés környezetének elérése a kezelőkben
A HandleRequirementAsync metódusnak két paramétere van: egy AuthorizationHandlerContext és a TRequirement kezelendő. Az olyan keretrendszerek, mint az MVC, vagy SignalR bármilyen objektumot hozzáadhatnak a Resource tulajdonsághoz, AuthorizationHandlerContext hogy további információkat adjanak át.
Végpont-útválasztás használatakor az engedélyezést általában az engedélyezési köztes szoftver kezeli. Ebben az esetben a Resource tulajdonság egy példánya a HttpContext-nek. A környezet az aktuális végpont eléréséhez használható, amely az útválasztás alapjául szolgáló erőforrás mintavételéhez használható. Például:
if (context.Resource is HttpContext httpContext)
{
var endpoint = httpContext.GetEndpoint();
var actionDescriptor = endpoint.Metadata.GetMetadata<ControllerActionDescriptor>();
...
}
A hagyományos útválasztásnál, vagy amikor az engedélyezés az MVC engedélyezési szűrőjének részeként történik, az Resource értéke egy AuthorizationFilterContext példány. Ez a tulajdonság hozzáférést biztosít az HttpContext, RouteData valamint az MVC és Razor Pages által biztosított összes többi elemhez.
A tulajdonság használata Resource keretrendszerfüggő. A tulajdonság információinak Resource használata bizonyos keretrendszerekre korlátozza az engedélyezési szabályzatokat. Adja le a Resource tulajdonságot a is kulcsszó használatával, majd győződjön meg arról, hogy a leadás sikeres volt, hogy a kód ne ütközjön össze más InvalidCastException keretrendszereken való futtatáskor:
// Requires the following import:
// using Microsoft.AspNetCore.Mvc.Filters;
if (context.Resource is AuthorizationFilterContext mvcContext)
{
// Examine MVC-specific things like routing data.
}
Globálisan minden felhasználó hitelesítésére van szükség
Ha tudni szeretné, hogyan követelheti meg globálisan az összes felhasználó hitelesítését, olvassa el Hitelesített felhasználók megkövetelésecímű témakört.
Engedélyezés külső szolgáltatásmintával
Az AspNetCore.Docs.Samples mintakódja bemutatja, hogyan valósíthat meg további engedélyezési követelményeket egy külső engedélyezési szolgáltatással. A mintaprojektet Contoso.API az Azure AD védi. A Contoso.Security.API projekt további engedélyezési ellenőrzése egy leíró csomagot ad vissza, amely meghatározza, hogy az Contoso.API ügyfélalkalmazás végrehajthatja-e a GetWeather API kérését.
A minta konfigurálása
Alkalmazás-nyilvántartás létrehozása a Microsoft Entra ID környezetében:
Rendeljen hozzá egy AppRole-t.
Az API-engedélyek alatt adja hozzá az AppRole-t engedélyként, és adjon rendszergazdai hozzájárulást. Vegye figyelembe, hogy ebben a beállításban ez az alkalmazásregisztráció az API-t és az API-t invokáló ügyfelet is jelöli. Tetszés szerint két alkalmazásregisztrációt hozhat létre. Ha ezt a beállítást használja, győződjön meg arról, hogy csak az API-engedélyeket hajtja végre, és csak az ügyfél engedélylépéseként adja hozzá az AppRole-t. Csak az ügyfélalkalmazás-regisztrációhoz szükséges egy titkos ügyfélkód létrehozása.
Konfigurálja a
Contoso.APIprojektet a következő beállításokkal:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "<Tenant name from AAD properties>.onmicrosoft.com",
"TenantId": "<Tenant Id from AAD properties>",
"ClientId": "<Client Id from App Registration representing the API>"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
- Konfigurálás
Contoso.Security.APIa következő beállításokkal:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"AllowedClients": [
"<Use the appropriate Client Id representing the Client calling the API>"
]
}
Nyissa meg a ContosoAPI.collection.json fájlt, és konfiguráljon egy környezetet a következőkkel:
-
ClientId: Az API-t hívó ügyfelet képviselő alkalmazásregisztrációból származó ügyfélazonosító. -
clientSecret: Az API-t hívó ügyfelet képviselő alkalmazásregisztrációból származó ügyfélkód. -
TenantId: Bérlő azonosító az AAD tulajdonságai közül
-
Bontsa ki a parancsokat a
ContosoAPI.collection.jsonfájlból, és használja őket cURL-parancsok létrehozására az alkalmazás teszteléséhez.Futtassa a megoldást, és használja a cURL-t az API meghívásához. Töréspontokat adhat hozzá a
Contoso.Security.API.SecurityPolicyController-ben, és megfigyelheti, hogy az ügyfél-azonosító átadásra kerül, amely annak megállapítására szolgál, hogy engedélyezett-e az időjárás lekérése.
További erőforrások
A borítók alatt a szerepköralapú engedélyezés és a jogcímalapú engedélyezés egy követelményt, egy követelménykezelőt és egy előre konfigurált szabályzatot használ. Ezek az építőelemek támogatják az engedélyezési értékelések kódban való kifejezését. Az eredmény egy gazdagabb, újrafelhasználható, tesztelhető engedélyezési struktúra.
Az engedélyezési szabályzatok egy vagy több követelményből állnak. Az engedélyezési szolgáltatás konfigurációjának részeként van regisztrálva a Startup.ConfigureServices következő módszerrel:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
services.AddAuthorization(options =>
{
options.AddPolicy("AtLeast21", policy =>
policy.Requirements.Add(new MinimumAgeRequirement(21)));
});
}
Az előző példában létrejön egy "AtLeast21" szabályzat. Egyetlen követelménye van– a minimális életkor, amelyet a követelmény paramétereként ad meg.
IAuthorizationService
Az elsődleges szolgáltatás, amely meghatározza, hogy az engedélyezés sikeres-e:IAuthorizationService
/// <summary>
/// Checks policy based permissions for a user
/// </summary>
public interface IAuthorizationService
{
/// <summary>
/// Checks if a user meets a specific set of requirements for the specified resource
/// </summary>
/// <param name="user">The user to evaluate the requirements against.</param>
/// <param name="resource">
/// An optional resource the policy should be checked with.
/// If a resource is not required for policy evaluation you may pass null as the value
/// </param>
/// <param name="requirements">The requirements to evaluate.</param>
/// <returns>
/// A flag indicating whether authorization has succeeded.
/// This value is <value>true</value> when the user fulfills the policy;
/// otherwise <value>false</value>.
/// </returns>
/// <remarks>
/// Resource is an optional parameter and may be null. Please ensure that you check
/// it is not null before acting upon it.
/// </remarks>
Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource,
IEnumerable<IAuthorizationRequirement> requirements);
/// <summary>
/// Checks if a user meets a specific authorization policy
/// </summary>
/// <param name="user">The user to check the policy against.</param>
/// <param name="resource">
/// An optional resource the policy should be checked with.
/// If a resource is not required for policy evaluation you may pass null as the value
/// </param>
/// <param name="policyName">The name of the policy to check against a specific
/// context.</param>
/// <returns>
/// A flag indicating whether authorization has succeeded.
/// Returns a flag indicating whether the user, and optional resource has fulfilled
/// the policy.
/// <value>true</value> when the policy has been fulfilled;
/// otherwise <value>false</value>.
/// </returns>
/// <remarks>
/// Resource is an optional parameter and may be null. Please ensure that you check
/// it is not null before acting upon it.
/// </remarks>
Task<AuthorizationResult> AuthorizeAsync(
ClaimsPrincipal user, object resource, string policyName);
}
Az előző kód az IAuthorizationService két metódusát emeli ki.
IAuthorizationRequirement metódusok nélküli jelölőszolgáltatás, és az engedélyezés sikerességének nyomon követésére szolgáló mechanizmus.
Mindegyik IAuthorizationHandler felelős annak ellenőrzéséért, hogy teljesülnek-e a követelmények:
/// <summary>
/// Classes implementing this interface are able to make a decision if authorization
/// is allowed.
/// </summary>
public interface IAuthorizationHandler
{
/// <summary>
/// Makes a decision if authorization is allowed.
/// </summary>
/// <param name="context">The authorization information.</param>
Task HandleAsync(AuthorizationHandlerContext context);
}
A AuthorizationHandlerContext kezelő az osztályt használja annak jelzésére, hogy teljesültek-e a követelmények:
context.Succeed(requirement)
Az alábbi kód az engedélyezési szolgáltatás egyszerűsített (megjegyzésekkel ellátott) alapértelmezett implementációját mutatja be:
public async Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user,
object resource, IEnumerable<IAuthorizationRequirement> requirements)
{
// Create a tracking context from the authorization inputs.
var authContext = _contextFactory.CreateContext(requirements, user, resource);
// By default this returns an IEnumerable<IAuthorizationHandlers> from DI.
var handlers = await _handlers.GetHandlersAsync(authContext);
// Invoke all handlers.
foreach (var handler in handlers)
{
await handler.HandleAsync(authContext);
}
// Check the context, by default success is when all requirements have been met.
return _evaluator.Evaluate(authContext);
}
Az alábbi kód egy tipikus ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
// Add all of your handlers to DI.
services.AddSingleton<IAuthorizationHandler, MyHandler1>();
// MyHandler2, ...
services.AddSingleton<IAuthorizationHandler, MyHandlerN>();
// Configure your policies
services.AddAuthorization(options =>
options.AddPolicy("Something",
policy => policy.RequireClaim("Permission", "CanViewPage", "CanViewAnything")));
services.AddControllersWithViews();
services.AddRazorPages();
}
Használja a IAuthorizationService vagy a [Authorize(Policy = "Something")] engedélyezéshez.
Szabályzatok alkalmazása az MVC-vezérlőre
Ha a Razor Oldalakat használja, olvassa el a Házirendek alkalmazása a Razor Oldalakra című témakört a dokumentumban.
A szabályzatok a szabályzat nevével ellátott attribútummal [Authorize] lesznek alkalmazva a vezérlőkre. Például:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
[Authorize(Policy = "AtLeast21")]
public class AlcoholPurchaseController : Controller
{
public IActionResult Index() => View();
}
Szabályzatok alkalmazása lapokra Razor
A szabályzatok alkalmazása a Razor Pagesre a házirend nevét tartalmazó [Authorize] attribútummal történik. Például:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
[Authorize(Policy = "AtLeast21")]
public class AlcoholPurchaseModel : PageModel
{
}
A szabályzatok nem alkalmazhatók az Razor lapkezelő szintjén, azokat az oldalra kell alkalmazni.
A házirendek jogosultsági konvencióval alkalmazhatók az oldalakra.
Requirements
Az engedélyezési követelmény olyan adatparaméterek gyűjteménye, amelyeket egy szabályzat az aktuális felhasználói főszereplő kiértékelésére használhat. Az "AtLeast21" szabályzatban a követelmény egyetlen paraméter – a minimális életkor. A követelmény valósítja meg IAuthorizationRequirement, amely egy üres jelölőinterfész. A paraméteres minimális életkorra vonatkozó követelmény az alábbiak szerint valósítható meg:
using Microsoft.AspNetCore.Authorization;
public class MinimumAgeRequirement : IAuthorizationRequirement
{
public int MinimumAge { get; }
public MinimumAgeRequirement(int minimumAge)
{
MinimumAge = minimumAge;
}
}
Ha egy engedélyezési szabályzat több engedélyezési követelményeket is tartalmaz, minden követelménynek teljesülnie kell ahhoz, hogy a szabályzat kiértékelése sikeres legyen. Más szóval, az egyetlen engedélyezési szabályzathoz hozzáadott több engedélyezési követelmény kezelése ÉS alapon történik.
Note
Egy követelménynek nem kell adatokkal vagy tulajdonságokkal rendelkeznie.
Engedélyezési kezelők
Egy követelmény tulajdonságainak kiértékeléséért egy engedélyezési kezelő felelős. Az engedélyezési kezelő kiértékeli a követelményeket a megadottak AuthorizationHandlerContext alapján annak megállapításához, hogy engedélyezett-e a hozzáférés.
Egy követelmény több kezelővel is rendelkezhet. A kezelő örökölhet AuthorizationHandler<TRequirement>, ahol TRequirement a kezelendő követelmény. Másik lehetőségként a kezelők egynél több követelménytípus kezelésére is implementálhatnak IAuthorizationHandler .
Kezelő használata egyetlen követelményhez
Az alábbi példa egy-az-egyhez kapcsolatot mutat be, amelyben egy minimális korú kezelő egyetlen követelményt használ:
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using PoliciesAuthApp1.Services.Requirements;
public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
MinimumAgeRequirement requirement)
{
if (!context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth &&
c.Issuer == "http://contoso.com"))
{
//TODO: 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 &&
c.Issuer == "http://contoso.com").Value);
int calculatedAge = DateTime.Today.Year - dateOfBirth.Year;
if (dateOfBirth > DateTime.Today.AddYears(-calculatedAge))
{
calculatedAge--;
}
if (calculatedAge >= requirement.MinimumAge)
{
context.Succeed(requirement);
}
//TODO: Use the following if targeting a version of
//.NET Framework older than 4.6:
// return Task.FromResult(0);
return Task.CompletedTask;
}
}
Az előző kód azt határozza meg, hogy az aktuális felhasználónév rendelkezik-e születési dátummal, amelyet egy ismert és megbízható kibocsátó állított ki. Az engedélyezés nem történhet meg, ha a kérelem hiányzik, ilyenkor visszaad egy befejezett feladatot. Ha egy jogcím jelen van, a rendszer kiszámítja a felhasználó életkorát. Ha a felhasználó megfelel a követelmény által meghatározott minimális életkornak, az engedélyezés sikeresnek minősül. Amikor az engedélyezés sikeres, context.Succeed az egyetlen paraméterként hívja meg az elégedett követelményt.
Kezelő használata több követelményhez
Az alábbi példa egy egy-a-többhöz kapcsolatot mutat be, amelyben egy engedélykezelő három különböző követelménytípust képes kezelni:
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using PoliciesAuthApp1.Services.Requirements;
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);
}
}
}
//TODO: 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;
}
}
Az előző kód bejárja a PendingRequirements-t — egy olyan tulajdonságot, amely nem sikeresnek jelölt követelményeket tartalmaz.
ReadPermission Egy követelmény esetében a felhasználónak tulajdonosnak vagy szponzornak kell lennie a kért erőforrás eléréséhez. Az EditPermission vagy DeletePermission követelmény esetén a felhasználónak tulajdonosnak kell lennie a kért erőforrás eléréséhez.
Kezelő regisztrációja
A kezelők a konfiguráció során regisztrálva vannak a szolgáltatásgyűjteményben. Például:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
services.AddAuthorization(options =>
{
options.AddPolicy("AtLeast21", policy =>
policy.Requirements.Add(new MinimumAgeRequirement(21)));
});
services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();
}
Az előző kód egyszeriként regisztrál MinimumAgeHandler a meghívással services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();. A kezelők bármelyik beépített szolgáltatási élettartamot felhasználva regisztrálhatók.
Összecsomagolhat egy követelményt és egy kezelőt egyetlen osztályban, amely megvalósítja mind a IAuthorizationRequirement-t, mind a IAuthorizationHandler-t. Ez a kötegelés szoros kapcsolatot hoz létre a kezelő és a követelmény között, és csak az egyszerű követelmények és kezelők számára ajánlott. Ha mindkét felületet megvalósító osztályt hoz létre, azzal nem kell regisztrálnia a kezelőt a DI-ben, mert a beépített rendszer PassThroughAuthorizationHandler lehetővé teszi a követelmények kezelését.
AssertionRequirement osztályában található egy jó példa, ahol a AssertionRequirement mind követelmény, mind kezelő, egy teljesen önálló osztályban.
Mit kell visszaadnia egy kezelőnek?
Vegye figyelembe, hogy a Handlekezelő példában szereplő metódus nem ad vissza értéket. Hogyan jelzi a sikeres vagy sikertelen állapotot?
A kezelő a sikert úgy jelzi, hogy hívást kezdeményez
context.Succeed(IAuthorizationRequirement requirement), átadva a sikeresen érvényesített követelményt.A kezelőknek általában nem kell kezelnie a hibákat, mivel ugyanazon követelmény más kezelői is sikeresek lehetnek.
A sikertelenség garantálásához, még akkor is, ha más követelménykezelők sikeresek, hívja meg a
context.Fail.
Ha egy kezelő hívásokat kezdeményez context.Succeed , vagy context.Failaz összes többi kezelőt továbbra is meghívja a rendszer. Ez lehetővé teszi, hogy a követelmények olyan mellékhatásokat okoznak, mint a naplózás, amely akkor is megtörténik, ha egy másik kezelő sikeresen érvényesített vagy meghiúsult egy követelményt. Ha be van falseállítva, a InvokeHandlersAfterFailure tulajdonság megszakítja a kezelők végrehajtását, amikor context.Fail meghívják.
InvokeHandlersAfterFailure alapértelmezés szerint true, ilyenkor az összes kezelőt meghívják.
Note
Az engedélyezési kezelőket akkor is meghívja a rendszer, ha a hitelesítés sikertelen.
Miért szeretnék több kezelőt egy követelményhez?
Azokban az esetekben, amikor a kiértékelést VAGY alapon szeretné elvégezni, egyetlen követelményhez több kezelőt kell implementálnia. A Microsoft például csak kulcskártyákkal nyitott ajtókkal rendelkezik. Ha otthon hagyja a kulcskártyát, a recepciós kinyomtat egy ideiglenes matricát, és megnyitja az ajtót. Ebben a forgatókönyvben egyetlen követelmény, a BuildingEntry, de több kezelő van, amelyek mindegyike egyetlen követelményt vizsgál.
BuildingEntryRequirement.cs
using Microsoft.AspNetCore.Authorization;
public class BuildingEntryRequirement : IAuthorizationRequirement
{
}
BadgeEntryHandler.cs
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using PoliciesAuthApp1.Services.Requirements;
public class BadgeEntryHandler : AuthorizationHandler<BuildingEntryRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
BuildingEntryRequirement requirement)
{
if (context.User.HasClaim(c => c.Type == "BadgeId" &&
c.Issuer == "http://microsoftsecurity"))
{
context.Succeed(requirement);
}
//TODO: 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.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using PoliciesAuthApp1.Services.Requirements;
public class TemporaryStickerHandler : AuthorizationHandler<BuildingEntryRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
BuildingEntryRequirement requirement)
{
if (context.User.HasClaim(c => c.Type == "TemporaryBadgeId" &&
c.Issuer == "https://microsoftsecurity"))
{
// We'd also check the expiration date on the sticker.
context.Succeed(requirement);
}
//TODO: Use the following if targeting a version of
//.NET Framework older than 4.6:
// return Task.FromResult(0);
return Task.CompletedTask;
}
}
Győződjön meg arról, hogy mindkét kezelő regisztrálva van. Ha bármelyik kezelő sikeres lesz, amikor egy szabályzat kiértékeli a BuildingEntryRequirementszabályzatot, a szabályzat kiértékelése sikeres lesz.
Szabályzat teljesítése func használatával
Előfordulhatnak olyan helyzetek, amikor egy szabályzat teljesítése egyszerűen kifejezhető kódban. A szabályzatnak a Func<AuthorizationHandlerContext, bool> szabályzatkészítővel való konfigurálásakor is meg lehet adni egy RequireAssertion beállítást.
Az előző BadgeEntryHandler például a következőképpen írható át:
services.AddAuthorization(options =>
{
options.AddPolicy("BadgeEntry", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c =>
(c.Type == "BadgeId" ||
c.Type == "TemporaryBadgeId") &&
c.Issuer == "https://microsoftsecurity")));
});
MVC-kérés környezetének elérése a kezelőkben
Az az engedélyezési kezelőben implementált HandleRequirementAsync metódusnak két paramétere van: egy AuthorizationHandlerContext és egy TRequirement, amit Ön kezel. Az olyan keretrendszerek, mint az MVC, vagy SignalR bármilyen objektumot hozzáadhatnak a Resource tulajdonsághoz, AuthorizationHandlerContext hogy további információkat adjanak át.
Végpont-útválasztás használatakor az engedélyezést általában az engedélyezési köztes szoftver kezeli. Ebben az esetben a Resource tulajdonság egy példánya a HttpContext-nek. A környezet az aktuális végpont eléréséhez használható, amely az útválasztás alapjául szolgáló erőforrás mintavételéhez használható. Például:
if (context.Resource is HttpContext httpContext)
{
var endpoint = httpContext.GetEndpoint();
var actionDescriptor = endpoint.Metadata.GetMetadata<ControllerActionDescriptor>();
...
}
A hagyományos útválasztásnál, vagy amikor az engedélyezés az MVC engedélyezési szűrőjének részeként történik, az Resource értéke egy AuthorizationFilterContext példány. Ez a tulajdonság hozzáférést biztosít az HttpContext, RouteData valamint az MVC és Razor Pages által biztosított összes többi elemhez.
A tulajdonság használata Resource keretrendszerfüggő. A tulajdonság információinak Resource használata bizonyos keretrendszerekre korlátozza az engedélyezési szabályzatokat. Adja le a Resource tulajdonságot a is kulcsszó használatával, majd győződjön meg arról, hogy a leadás sikeres volt, hogy a kód ne ütközjön össze más InvalidCastException keretrendszereken való futtatáskor:
// Requires the following import:
// using Microsoft.AspNetCore.Mvc.Filters;
if (context.Resource is AuthorizationFilterContext mvcContext)
{
// Examine MVC-specific things like routing data.
}
Globálisan minden felhasználó hitelesítésére van szükség
Ha tudni szeretné, hogyan követelheti meg globálisan az összes felhasználó hitelesítését, olvassa el Hitelesített felhasználók megkövetelésecímű témakört.