Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Kapakların altında rol tabanlı yetkilendirme ve talep tabanlı yetkilendirme bir gereksinim, gereksinim işleyicisi ve önceden yapılandırılmış bir ilke kullanır. Bu yapı taşları kodda yetkilendirme değerlendirmelerinin ifadesini destekler. Sonuç daha zengin, yeniden kullanılabilir, test edilebilir bir yetkilendirme yapısıdır.
Yetkilendirme ilkesi bir veya daha fazla gereksinimden oluşur. Yetkilendirme hizmeti yapılandırmasının bir parçası olarak uygulamanın Program.cs
dosyasına kaydedin:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AtLeast21", policy =>
policy.Requirements.Add(new MinimumAgeRequirement(21)));
});
Yukarıdaki örnekte bir "AtLeast21" ilkesi oluşturulur. Tek bir gereksinimi vardır; minimum yaş, gereksinime parametre olarak sağlanır.
YetkilendirmeServisi
Yetkilendirmenin başarılı olup olmadığını belirleyen birincil hizmet: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);
}
Yukarıdaki kod, IAuthorizationService'in iki yöntemini vurgular.
IAuthorizationRequirement yöntemi olmayan bir işaretçi hizmetidir ve yetkilendirmenin başarılı olup olmadığını izlemeye yönelik mekanizmadır.
Her IAuthorizationHandler biri gereksinimlerin karşılandığından sorumludur:
/// <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);
}
AuthorizationHandlerContext sınıfı, işleyicinin gereksinimlerin karşılanıp karşılanmadığını işaretlemek için kullandığı sınıftır:
context.Succeed(requirement)
Aşağıdaki kod, yetkilendirme hizmetinin basitleştirilmiş (ve açıklamalarla ek açıklamalı) varsayılan uygulamasını gösterir:
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);
}
Aşağıdaki kod tipik bir yetkilendirme hizmeti yapılandırmasını gösterir:
// 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")));
Yetkilendirme için , IAuthorizationServiceveya [Authorize(Policy = "Something")]
kullanınRequireAuthorization("Something")
.
MVC denetleyicilerine ilkeleri uygulayın
Sayfaları kullanan Razor uygulamalar için Razor Sayfaları için ilkeleri uygulama bölümüne bakın.
Denetleyicilere ilke adı özniteliğini [Authorize]
kullanarak ilkeleri uygulayın.
[Authorize(Policy = "AtLeast21")]
public class AtLeast21Controller : Controller
{
public IActionResult Index() => View();
}
Denetleyici ve eylem düzeylerinde birden çok ilke uygulanırsa, erişim verilmeden önce tüm ilkelerin geçmesi gerekir:
[Authorize(Policy = "AtLeast21")]
public class AtLeast21Controller2 : Controller
{
[Authorize(Policy = "IdentificationValidated")]
public IActionResult Index() => View();
}
Razor Sayfalara politikalar uygulama
İlke adı özniteliğini Razor Pages üzerinde [Authorize]
kullanarak ilkeleri uygulayın. Örneğin:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace AuthorizationPoliciesSample.Pages;
[Authorize(Policy = "AtLeast21")]
public class AtLeast21Model : PageModel { }
İlkeler Sayfa işleyici düzeyinde uygulanamıyorRazor, Sayfaya uygulanmalıdır.
İlkeler, yetkilendirme Razor kullanılarak Sayfalar'a da uygulanabilir.
Uç noktalara politikalar uygulama
Uç noktalara ilkeler uygulamak için ilke adıyla RequireAuthorization kullanın. Örneğin:
app.MapGet("/helloworld", () => "Hello World!")
.RequireAuthorization("AtLeast21");
Gereksinimler
Yetkilendirme gereksinimi, bir ilkenin geçerli kullanıcı sorumlusunu değerlendirmek için kullanabileceği veri parametreleri koleksiyonudur. "AtLeast21" ilkemizde gereksinim tek bir parametredir( en düşük yaş). Bir gereksinim, boş bir işaretçi arabirimi olan IAuthorizationRequirement'ü uygular. Parametreli minimum yaş gereksinimi aşağıdaki gibi uygulanabilir:
using Microsoft.AspNetCore.Authorization;
namespace AuthorizationPoliciesSample.Policies.Requirements;
public class MinimumAgeRequirement : IAuthorizationRequirement
{
public MinimumAgeRequirement(int minimumAge) =>
MinimumAge = minimumAge;
public int MinimumAge { get; }
}
Yetkilendirme ilkesi birden çok yetkilendirme gereksinimi içeriyorsa, ilke değerlendirmesinin başarılı olması için tüm gereksinimlerin geçmesi gerekir. Başka bir deyişle, tek bir yetkilendirme ilkesine eklenen birden çok yetkilendirme gereksinimi VE temelinde ele alınır.
Not
Bir gereksinimin veri veya özelliklere sahip olması gerekmez.
Yetkilendirme işleyicileri
Yetkilendirme işleyicisi, bir gereksinimin özelliklerinin değerlendirilmesinden sorumludur. Yetkilendirme işleyicisi, erişime izin verilip verilmediğini belirlemek için sağlanana AuthorizationHandlerContext göre gereksinimleri değerlendirir.
Bir gereksinim birden çok işleyiciye sahip olabilir. Bir işleyici AuthorizationHandler<TRequirement> devralabilir, burada TRequirement
işlenmesi gereken bir gereksinimdir. Alternatif olarak, bir işleyici birden fazla gereksinim türünü işlemek için doğrudan uygulayabilir IAuthorizationHandler .
Bir gereksinim için işleyici kullan
Aşağıdaki örnekte, en düşük yaş işleyicisinin tek bir gereksinimi işlediği bire bir ilişki gösterilmektedir:
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;
}
}
Yukarıdaki kod, geçerli kullanıcı ilkesinin bilinen ve güvenilen bir Veren tarafından verilmiş bir doğum tarihi talebinde bulunup bulunmadığını belirler. Talep eksik olduğunda yetkilendirme gerçekleşemez ve bu durumda tamamlanmış bir görev döndürülür. Talep mevcut olduğunda kullanıcının yaşı hesaplanır. Kullanıcı gereksinim tarafından tanımlanan en düşük yaşı karşılıyorsa yetkilendirme başarılı kabul edilir. Yetkilendirme başarılı olduğunda, context.Succeed
karşılanan gereksinimle tek parametre olarak çağrılır.
Birden çok gereksinim için işleyici kullanma
Aşağıdaki örnekte, bir izin işleyicisinin üç farklı gereksinim türünü işleyebildiği bire çok ilişkisi gösterilmektedir:
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;
}
}
Önceki kod, başarılı olarak işaretlenmemiş gereksinimler içeren PendingRequirements özelliğini dolaşır.
ReadPermission
Bir gereksinim için kullanıcının istenen kaynağa erişmek için sahip veya sponsor olması gerekir.
EditPermission
veya DeletePermission
gereksinimi için, istenen kaynağa erişmek için sahip olmaları gerekir.
İşleyici kaydı
Yapılandırma sırasında hizmet koleksiyonuna işleyicileri kaydedin. Örneğin:
builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();
Önceki kod MinimumAgeHandler
öğesini "singleton" olarak kaydeder. İşleyiciler yerleşik hizmet ömründen herhangi biri kullanılarak kaydedilebilir.
Hem gereksinimi hem de işleyiciyi IAuthorizationRequirement ve IAuthorizationHandler uygulayan tek bir sınıfa paketlemek mümkündür. Bu paketleme işleyici ile gereksinim arasında sıkı bir bağlantı oluşturur ve yalnızca basit gereksinimler ve işleyiciler için önerilir. Her iki arabirimi de uygulayan bir sınıf oluşturmak, gereksinimlerin kendilerini işlemelerini sağlayan yerleşik PassThroughAuthorizationHandler özelliği nedeniyle işleyiciyi DI'ye kaydetme gerekliliğini ortadan kaldırır.
AssertionRequirement sınıfının uygulamasına, hem bir gereksinim hem de tam anlamıyla bağımsız bir sınıfta işleyici olan AssertionRequirement için iyi bir örnek olarak bakın.
Bir işleyici ne döndürmelidir?
İşleyici örneğindekiHandle
değer döndürmediğini unutmayın. Başarı veya başarısızlık durumu nasıl belirtilir?
İşleyici, başarıyla doğrulanan gereksinimi geçirerek
context.Succeed(IAuthorizationRequirement requirement)
öğesini çağırarak başarıyı gösterir.Aynı gereksinime yönelik diğer işleyiciler başarılı olabileceğinden, işleyicinin hataları genel olarak işlemesi gerekmez.
Başarısızlığı garanti altına almak için, diğer gereksinim işleyicileri başarılı olsa bile
context.Fail
işlevini çağırın.
Eğer bir işleyici context.Succeed
veya context.Fail
çağırırsa, diğer tüm işleyiciler yine de çağrılır. Bu, başka bir işleyici bir gereksinimi başarıyla doğrulasa veya başarısız olsa bile günlüğe kaydetme gibi yan etkilerin oluşmasına olanak tanır.
false
olarak ayarlandığında, InvokeHandlersAfterFailure özelliği, context.Fail
çağrıldığında işleyicilerin yürütülmesini kısa devre yapar.
InvokeHandlersAfterFailure
varsayılan değeridir true
ve bu durumda tüm işleyiciler çağrılır.
Not
Kimlik doğrulaması başarısız olsa bile yetkilendirme işleyicileri çağrılır. Ayrıca işleyiciler herhangi bir sırada yürütülebilir, bu nedenle belirli bir sırada çağrılmalarına bağımlı değildir.
Neden bir gereksinim için birden çok işleyici isteyebilirim?
Değerlendirmenin VEYA esasına göre yapılmasını istediğiniz durumlarda tek bir gereksinim için birden çok işleyici uygulayın. Örneğin, Microsoft'un yalnızca anahtar kartlarıyla açılan kapıları vardır. Anahtar kartınızı evde bırakırsanız resepsiyonist geçici bir çıkartma yazdırır ve kapıyı sizin için açar. Bu senaryoda, BuildingEntry adlı tek bir gereksiniminiz olur, ancak her biri bu tek gereksinimi inceleyen birden çok işleyiciye sahipsiniz.
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;
}
}
Her iki işleyicinin de kayıtlı olduğundan emin olun. Bir politika BuildingEntryRequirement
değerlendirirken işleyicilerden herhangi biri başarılı olursa, politika değerlendirmesi başarılı olur.
İlkeyi yerine getirmek için bir fonksiyon kullanın
bir ilkeyi yerine getirmenin kodla ifade edilmesi kolay olduğu durumlar olabilir. Politika Func<AuthorizationHandlerContext, bool>
oluşturucusu ile bir ilkeyi yapılandırırken bir RequireAssertion
sağlamak mümkündür.
Örneğin, önceki BadgeEntryHandler
aşağıdaki gibi yeniden yazılabilir:
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")));
});
İşleyicilerde MVC isteği bağlamı erişimi
yöntemi iki HandleRequirementAsync
parametreye sahiptir: an AuthorizationHandlerContext
ve TRequirement
işleniyor. Ek bilgi aktarmak için MVC gibi çerçeveler veya SignalR, Resource
üzerindeki AuthorizationHandlerContext
özelliğine herhangi bir nesne eklemekte özgürdür.
Uç nokta yönlendirme kullanılırken yetkilendirme genellikle Yetkilendirme Ara Yazılımı tarafından işlenir. Bu durumda, Resource
özelliği HttpContext bir örneğidir. Bağlam geçerli uç noktaya erişmek için kullanılabilir ve bu da yönlendirme yaptığınız temel kaynağı araştırmak için kullanılabilir. Örneğin:
if (context.Resource is HttpContext httpContext)
{
var endpoint = httpContext.GetEndpoint();
var actionDescriptor = endpoint.Metadata.GetMetadata<ControllerActionDescriptor>();
...
}
Geleneksel yönlendirmede veya MVC'nin yetkilendirme filtresinin bir parçası olarak yetkilendirme gerçekleştiğinde, Resource
bir AuthorizationFilterContext örneğidir. Bu özellik, HttpContext
, MVC ve RouteData
Sayfaları tarafından sağlanan diğer her şeye ve Razor'ye erişim sağlar.
Resource
özelliğinin kullanımı çerçeveye özgüdür. özelliğindeki Resource
bilgileri kullanmak yetkilendirme ilkelerinizi belirli çerçevelerle sınırlar.
Resource
özelliğini is
anahtar sözcüğünü kullanarak dönüştürün ve ardından atamanın başarılı olduğunu onaylayarak kodunuzun diğer çerçevelerde çalıştırıldığında bir InvalidCastException
ile çökmediğinden emin olun.
// Requires the following import:
// using Microsoft.AspNetCore.Mvc.Filters;
if (context.Resource is AuthorizationFilterContext mvcContext)
{
// Examine MVC-specific things like routing data.
}
Genel olarak tüm kullanıcıların kimliğinin doğrulanması gerekir
Genel olarak tüm kullanıcıların kimliğinin doğrulanmış olmasını gerektirme hakkında bilgi için bkz . Kimliği doğrulanmış kullanıcılar gerektirme.
Dış hizmet örneğiyle yetkilendirme
AspNetCore.Docs.Samples üzerindeki örnek kod, bir dış yetkilendirme hizmetiyle ek yetkilendirme gereksinimlerini nasıl uygulayacaklarını gösterir. Örnek Contoso.API
projenin güvenliği Azure AD ile sağlanır. Projeden yapılan ek bir yetki kontrolü, istemci uygulamasının Contoso.Security.API
Contoso.API
API'yi çağırıp çağıramayacağına dair bir yük döndürür.
Örneği yapılandırın
Microsoft Entra Id kiracınızda bir uygulama kaydı oluşturun:
Bir AppRole atayın.
API izinleri'nin altında AppRole'ı izin olarak ekleyin ve Yönetici onayı verin. Bu kurulumda, bu uygulama kaydının hem API'yi hem de API'yi çağıran istemciyi temsil ettiğini unutmayın. İsterseniz iki uygulama kaydı oluşturabilirsiniz. Bu kurulumu kullanıyorsanız, yalnızca API izinlerini gerçekleştirdiğinizden emin olun, appRole'u yalnızca istemci için izin adımı olarak ekleyin. Yalnızca istemci uygulama kaydı için bir istemci sırrı oluşturulması gerekir.
Contoso.API
Projeyi aşağıdaki ayarlarla yapılandırın:
{
"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": "*"
}
- Aşağıdaki ayarlarla yapılandırın
Contoso.Security.API
:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"AllowedClients": [
"<Use the appropriate Client Id representing the Client calling the API>"
]
}
ContosoAPI.collection.json dosyasını açın ve aşağıdakilerle bir ortam yapılandırın:
-
ClientId
: API'yi çağıran istemciyi temsil eden uygulama kaydından istemci kimliği. -
clientSecret
: API'yi çağıran istemciyi temsil eden uygulama kaydındaki İstemci Gizli Anahtarı. -
TenantId
: AAD özelliklerinden kiracı kimliği
-
Dosyadan
ContosoAPI.collection.json
komutları ayıklayın ve uygulamayı test etmek için cURL komutları oluşturmak için kullanın.Çözümü çalıştırın ve API'yi çağırmak için cURL kullanın. öğesine
Contoso.Security.API.SecurityPolicyController
kesme noktaları ekleyebilir ve hava durumunu alma izninin verilip verilmeyeceğini onaylamada kullanılan istemci kimliğinin geçirildiğini gözlemleyebilirsiniz.
Ek kaynaklar
Örtülerin altında, rol tabanlı yetkilendirme ve talep tabanlı yetkilendirme, bir gereksinim, gereksinim işleyicisi ve önceden yapılandırılmış bir ilke kullanır. Bu yapı taşları kodda yetkilendirme değerlendirmelerinin ifadesini destekler. Sonuç daha zengin, yeniden kullanılabilir, test edilebilir bir yetkilendirme yapısıdır.
Yetkilendirme ilkesi bir veya daha fazla gereksinimden oluşur. Yetkilendirme hizmeti yapılandırmasının bir parçası olarak, Startup.ConfigureServices
yönteminde kaydedilir.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
services.AddAuthorization(options =>
{
options.AddPolicy("AtLeast21", policy =>
policy.Requirements.Add(new MinimumAgeRequirement(21)));
});
}
Yukarıdaki örnekte bir "AtLeast21" ilkesi oluşturulur. Tek bir gereksinimi vardır; minimum yaş, gereksinime parametre olarak sağlanır.
YetkilendirmeServisi
Yetkilendirmenin başarılı olup olmadığını belirleyen birincil hizmet: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);
}
Yukarıdaki kod, IAuthorizationService'in iki yöntemini vurgular.
IAuthorizationRequirement yöntemi olmayan bir işaretçi hizmetidir ve yetkilendirmenin başarılı olup olmadığını izlemeye yönelik mekanizmadır.
Her IAuthorizationHandler biri gereksinimlerin karşılandığından sorumludur:
/// <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);
}
AuthorizationHandlerContext sınıfı, işleyicinin gereksinimlerin karşılanıp karşılanmadığını işaretlemek için kullandığı sınıftır:
context.Succeed(requirement)
Aşağıdaki kod, yetkilendirme hizmetinin basitleştirilmiş (ve açıklamalarla ek açıklamalı) varsayılan uygulamasını gösterir:
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);
}
Aşağıdaki kod tipik bir ConfigureServices
gösterir:
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();
}
Yetkilendirme için IAuthorizationService veya [Authorize(Policy = "Something")]
kullanın.
MVC denetleyicisine ilke uygulama
Pages kullanıyorsanız Razor, bu belgede Razor Pages'e politikaları uygulama konusuna bakın.
Denetleyicilere ilkeler, ilke adı [Authorize]
özniteliği kullanılarak uygulanır. Örneğin:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
[Authorize(Policy = "AtLeast21")]
public class AlcoholPurchaseController : Controller
{
public IActionResult Index() => View();
}
Razor Sayfalara politikalar uygulama
Politikalar, politika adıyla Razor özniteliği kullanılarak [Authorize]
Sayfalara uygulanır. Örneğin:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
[Authorize(Policy = "AtLeast21")]
public class AlcoholPurchaseModel : PageModel
{
}
İlkeler Sayfa işleyici düzeyinde uygulanamıyorRazor, Sayfaya uygulanmalıdır.
İlkeler, yetkilendirme Razor kullanılarak Sayfalar'a uygulanabilir.
Gereksinimler
Yetkilendirme gereksinimi, bir ilkenin geçerli kullanıcı sorumlusunu değerlendirmek için kullanabileceği veri parametreleri koleksiyonudur. "AtLeast21" ilkemizde gereksinim tek bir parametredir( en düşük yaş). Bir gereksinim, boş bir işaretçi arabirimi olan IAuthorizationRequirement'ü uygular. Parametreli minimum yaş gereksinimi aşağıdaki gibi uygulanabilir:
using Microsoft.AspNetCore.Authorization;
public class MinimumAgeRequirement : IAuthorizationRequirement
{
public int MinimumAge { get; }
public MinimumAgeRequirement(int minimumAge)
{
MinimumAge = minimumAge;
}
}
Yetkilendirme ilkesi birden çok yetkilendirme gereksinimi içeriyorsa, ilke değerlendirmesinin başarılı olması için tüm gereksinimlerin geçmesi gerekir. Başka bir deyişle, tek bir yetkilendirme ilkesine eklenen birden çok yetkilendirme gereksinimi VE temelinde ele alınır.
Not
Bir gereksinimin veri veya özelliklere sahip olması gerekmez.
Yetkilendirme işleyicileri
Yetkilendirme işleyicisi, bir gereksinimin özelliklerinin değerlendirilmesinden sorumludur. Yetkilendirme işleyicisi, erişime izin verilip verilmediğini belirlemek için sağlanana AuthorizationHandlerContext göre gereksinimleri değerlendirir.
Bir gereksinim birden çok işleyiciye sahip olabilir. Bir işleyici AuthorizationHandler<TRequirement> devralabilir, burada TRequirement
işlenmesi gereken bir gereksinimdir. Alternatif olarak, bir işleyici birden fazla gereksinim türünü işlemek için uygulayabilir IAuthorizationHandler .
Bir gereksinim için işleyici kullan
Aşağıdaki örnekte, en düşük yaş işleyicisinin tek bir gereksinimi kullandığı bire bir ilişki gösterilmektedir:
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;
}
}
Yukarıdaki kod, geçerli kullanıcı ilkesinin bilinen ve güvenilen bir Veren tarafından verilmiş bir doğum tarihi talebinde bulunup bulunmadığını belirler. Talep eksik olduğunda yetkilendirme gerçekleşemez ve bu durumda tamamlanmış bir görev döndürülür. Talep mevcut olduğunda kullanıcının yaşı hesaplanır. Kullanıcı gereksinim tarafından tanımlanan en düşük yaşı karşılıyorsa yetkilendirme başarılı kabul edilir. Yetkilendirme başarılı olduğunda, context.Succeed
karşılanan gereksinimle tek parametre olarak çağrılır.
Birden çok gereksinim için işleyici kullanma
Aşağıdaki örnekte, bir izin işleyicisinin üç farklı gereksinim türünü işleyebildiği bire çok ilişkisi gösterilmektedir:
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;
}
}
Önceki kod, başarılı olarak işaretlenmemiş gereksinimler içeren PendingRequirements özelliğini dolaşır.
ReadPermission
Bir gereksinim için kullanıcının istenen kaynağa erişmek için sahip veya sponsor olması gerekir.
EditPermission
Veya DeletePermission
gereksinimi için kullanıcının istenen kaynağa erişebilmesi için sahip olması gerekir.
İşleyici kaydı
İşleyiciler yapılandırma sırasında hizmet koleksiyonuna kaydedilir. Örneğin:
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>();
}
Önceki kod, MinimumAgeHandler
tekil bir nesne olarak kaydederken services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();
çağırır. İşleyiciler yerleşik hizmet ömründen herhangi biri kullanılarak kaydedilebilir.
Hem gereksinimi hem de işleyiciyi IAuthorizationRequirement ve IAuthorizationHandler uygulayan tek bir sınıfta paketlemek mümkündür. Bu paketleme işleyici ile gereksinim arasında sıkı bir bağlantı oluşturur ve yalnızca basit gereksinimler ve işleyiciler için önerilir. Her iki arabirimi de uygulayan bir sınıf oluşturmak, gereksinimlerin kendilerini işlemesini sağlayan yerleşik PassThroughAuthorizationHandler nedeniyle işleyiciyi DI'ye kaydetme gereksinimini ortadan kaldırır.
Tamamen kendi kendine yeten bir sınıfta hem gereksinim hem de işleyici olan iyi bir örnek için AssertionRequirement sınıfını inceleyin.AssertionRequirement
Bir işleyici ne döndürmelidir?
İşleyici örneğindekiHandle
değer döndürmediğini unutmayın. Başarı veya başarısızlık durumu nasıl belirtilir?
İşleyici, başarıyla doğrulanan gereksinimi geçirerek
context.Succeed(IAuthorizationRequirement requirement)
öğesini çağırarak başarıyı gösterir.Aynı gereksinime yönelik diğer işleyiciler başarılı olabileceğinden, işleyicinin hataları genel olarak işlemesi gerekmez.
Başarısızlığı garanti altına almak için, diğer gereksinim işleyicileri başarılı olsa bile
context.Fail
işlevini çağırın.
Eğer bir işleyici context.Succeed
veya context.Fail
çağırırsa, diğer tüm işleyiciler yine de çağrılır. Bu, başka bir işleyici bir gereksinimi başarıyla doğrulasa veya başarısız olsa bile günlüğe kaydetme gibi yan etkilerin oluşmasına olanak tanır.
false
olarak ayarlandığında, InvokeHandlersAfterFailure özelliği, context.Fail
çağrıldığında işleyicilerin yürütülmesini kısa devre yapar.
InvokeHandlersAfterFailure
varsayılan değeridir true
ve bu durumda tüm işleyiciler çağrılır.
Not
Kimlik doğrulaması başarısız olsa bile yetkilendirme işleyicileri çağrılır.
Neden bir gereksinim için birden çok işleyici isteyebilirim?
Değerlendirmenin VEYA esasına göre yapılmasını istediğiniz durumlarda tek bir gereksinim için birden çok işleyici uygulayın. Örneğin, Microsoft'un yalnızca anahtar kartlarıyla açılan kapıları vardır. Anahtar kartınızı evde bırakırsanız resepsiyonist geçici bir çıkartma yazdırır ve kapıyı sizin için açar. Bu senaryoda, BuildingEntry adlı tek bir gereksiniminiz olur, ancak her biri bu tek gereksinimi inceleyen birden çok işleyiciye sahipsiniz.
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;
}
}
Her iki işleyicinin de kayıtlı olduğundan emin olun. Bir politika BuildingEntryRequirement
değerlendirirken işleyicilerden herhangi biri başarılı olursa, politika değerlendirmesi başarılı olur.
İlkeyi yerine getirmek için bir fonksiyon kullanın
bir ilkeyi yerine getirmenin kodla ifade edilmesi kolay olduğu durumlar olabilir. İlkenizi yapılandırırken ilke oluşturucu ile bir Func<AuthorizationHandlerContext, bool>
sağlamanız mümkündür.
Örneğin, önceki BadgeEntryHandler
aşağıdaki gibi yeniden yazılabilir:
services.AddAuthorization(options =>
{
options.AddPolicy("BadgeEntry", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c =>
(c.Type == "BadgeId" ||
c.Type == "TemporaryBadgeId") &&
c.Issuer == "https://microsoftsecurity")));
});
İşleyicilerde MVC isteği bağlamı erişimi
Yetkilendirme HandleRequirementAsync
işleyicisinde uyguladığınız yöntemin iki parametresi vardır: bir AuthorizationHandlerContext
ve işlediğiniz TRequirement
. Ek bilgi aktarmak için MVC gibi çerçeveler veya SignalR, Resource
üzerindeki AuthorizationHandlerContext
özelliğine herhangi bir nesne eklemekte özgürdür.
Uç nokta yönlendirme kullanılırken yetkilendirme genellikle Yetkilendirme Ara Yazılımı tarafından işlenir. Bu durumda, Resource
özelliği HttpContext bir örneğidir. Bağlam geçerli uç noktaya erişmek için kullanılabilir ve bu da yönlendirme yaptığınız temel kaynağı araştırmak için kullanılabilir. Örneğin:
if (context.Resource is HttpContext httpContext)
{
var endpoint = httpContext.GetEndpoint();
var actionDescriptor = endpoint.Metadata.GetMetadata<ControllerActionDescriptor>();
...
}
Geleneksel yönlendirmede veya MVC'nin yetkilendirme filtresinin bir parçası olarak yetkilendirme gerçekleştiğinde, Resource
bir AuthorizationFilterContext örneğidir. Bu özellik, HttpContext
, MVC ve RouteData
Sayfaları tarafından sağlanan diğer her şeye ve Razor'ye erişim sağlar.
Resource
özelliğinin kullanımı çerçeveye özgüdür. özelliğindeki Resource
bilgileri kullanmak yetkilendirme ilkelerinizi belirli çerçevelerle sınırlar.
Resource
özelliğini is
anahtar sözcüğünü kullanarak dönüştürün ve ardından atamanın başarılı olduğunu onaylayarak kodunuzun diğer çerçevelerde çalıştırıldığında bir InvalidCastException
ile çökmediğinden emin olun.
// Requires the following import:
// using Microsoft.AspNetCore.Mvc.Filters;
if (context.Resource is AuthorizationFilterContext mvcContext)
{
// Examine MVC-specific things like routing data.
}
Genel olarak tüm kullanıcıların kimliğinin doğrulanması gerekir
Genel olarak tüm kullanıcıların kimliğinin doğrulanmış olmasını gerektirme hakkında bilgi için bkz . Kimliği doğrulanmış kullanıcılar gerektirme.
ASP.NET Core