Autorizace na základě rolí v ASP.NET Core

Když se po ověření vytvoří identita uživatele, může uživatel patřit do jedné nebo více rolí, což odpovídá různým autorizacím, které musí uživatel získat přístup k datům a provádět operace. Například Tracy může patřit do rolí Správce a Uživatel s přístupem k webovým stránkám pro správu v aplikaci, zatímco Scott může patřit jenom do role Uživatel a nemá přístup k datům nebo operacím správy. Způsob vytváření a správa těchto rolí závisí na záložním úložišti procesu autorizace. Role jsou zpřístupněny vývojáři prostřednictvím ClaimsPrincipal.IsInRole. AddRoles musí být volána při nastavování systému identit aplikace, aby se přidaly služby rolí.

Zatímco role jsou deklarace identity, ne všechny deklarace identity jsou role. V závislosti na vystaviteli identity může být role seskupením uživatelů, kteří mohou uplatňovat nároky pro členy skupiny, stejně jako skutečný nárok na identitu. Deklarace mají být informace o jednotlivém uživateli. Použití rolí k přidání nároků uživateli může vést k nejasnosti ohledně hranice mezi uživatelem a jejich jednotlivými nároky. Právě zmatek je důvod, proč šablony jednostránkové aplikace (SPA) nejsou navrženy kolem rolí. Kromě toho, u organizací, které migrují z místního staršího systému, může rozmnožení rolí během let znamenat, že deklarace role může být příliš velká, aby byla obsažena v tokenu použitelném pro SPA. Pokud chcete zabezpečit služby SPA, přečtěte si téma Použití Identity k zabezpečení back-endu webového rozhraní API pro služby SPA.

Tento článek používá Razor příklady komponent a zaměřuje se na Blazor scénáře autorizace. Další pokyny najdete v části Další Blazorzdroje informací . Pokyny ke Razor stránkám a MVC najdete v následujících zdrojích informací:

konfigurace Identity se změnila s verzí .NET 6. Příklady v tomto článku ukazují přístupy, které konfigurují Identity služby v souboru aplikace Program . U aplikací .NET před vydáním .NET 6 (a před vydáním Blazor Web App s .NET 8) jsou služby nakonfigurované v Startup.ConfigureServices souboru Startup.cs. Syntaxe konfigurace Identity je zobrazena v článku o autorizaci na základě rolí na doprovodných Razor stránkách a článku o autorizaci na základě rolí v MVC. Podívejte se na předchozí zdroje a nastavte selektor verze dokumentace na verzi .NET, na kterou vaše aplikace cílí.

Ukázková aplikace

Ukázka Blazor Web App pro tento článek je ukázková aplikace BlazorWebAppAuthorization (dotnet/AspNetCore.Docs.Samples GitHub úložiště) (jak stáhnout). Ukázková aplikace používá počáteční účty s předkonfigurovanými rolemi k předvedení většiny příkladů v tomto článku. Další informace najdete v ukázkovém souboru README (README.md).

Upozornění

Tato ukázková aplikace používá k ukládání informací o uživatelích databázi v paměti, která není vhodná pro produkční scénáře. Ukázková aplikace je určená jenom pro demonstrační účely a neměla by se používat jako výchozí bod pro produkční aplikace.

Přidejte služby rolí k Identity

Zaregistrujte služby pro autorizaci podle rolí v souboru Program voláním AddRoles s typem role v konfiguraci aplikace Identity. Typ role v následujícím příkladu je IdentityRole:

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

Předchozí kód vyžaduje Microsoft.AspNetCore.Identity.UI balíček NuGet a direktivu using pro Microsoft.AspNetCore.Identity.

V případech, kdy aplikace přebírá podrobné řízení pro ruční sestavení Identity, zavolejte AddRoles na AddIdentityCore:

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

Zaregistrujte autorizační služby založené na rolích v Startup.ConfigureServices (Startup.cs) tím, že v konfiguraci aplikace AddRoles zavoláte Identity s typem role. Typ role v následujícím příkladu je IdentityRole:

services.AddDefaultIdentity<IdentityUser>()
    .AddRoles<IdentityRole>()
    ...

Předchozí kód vyžaduje Microsoft.AspNetCore.Identity.UI balíček NuGet a direktivu using pro Microsoft.AspNetCore.Identity.

V případech, kdy aplikace přebírá podrobné řízení pro ruční sestavení Identity, zavolejte AddRoles na AddIdentityCore:

services.AddIdentityCore<IdentityUser>()
    .AddRoles<IdentityRole>()
    ...

V Blazor Web Apps (.NET 8 nebo novější) není vyžadováno volání UseAuthorization v souboru Program.

V Blazor Server aplikacích zavolejte UseAuthorization ve Program souboru za řádkem, který volá UseAuthentication (pokud je k dispozici):

app.UseAuthentication(); // Only present if not called internally
app.UseAuthorization();

V aplikacích Blazor Server (ne Blazor Web App), zavolejte UseAuthorization ve Program souboru za řádkem, který volá UseAuthentication (pokud je k dispozici):

app.UseAuthentication(); // Only present if not called internally
app.UseAuthorization();

Ve Blazor Server aplikacích (nikoli Blazor Web App), zavolejte UseAuthorization, v Startup.Configure (Startup.cs), po řádku, který volá UseAuthentication (pokud je k dispozici):

app.UseAuthentication(); // Only present if not called internally
app.UseAuthorization();

Blazor WebAssembly aplikace volají AddAuthorizationCore do Program souboru, aby se přidaly autorizační služby:

builder.Services.AddAuthorizationCore();

Kontroly autorizace založené na rolích

Kontroly autorizace na základě role:

Komponenta AuthorizeView (AuthorizeView součást v Blazor dokumentaci) podporuje autorizaci na základě role . Tato část se zabývá základními koncepty. Úplné pokrytí najdete v tématu ASP.NET Core Blazor ověřování a autorizace.

Pro autorizaci obsahu v Razor komponentách na základě role použijte AuthorizeView.Roles parametr.

V následujícím příkladu:

  • Aby uživatel viděl obsah první Admin komponenty, musí mít deklaraci role pro buď SuperUser nebo AuthorizeView.
  • Pro vyžadování jak deklarace role Admin, tak SuperUser, druhý příklad vnořuje komponenty AuthorizeView.

Pages/RoleChecksWithAuthorizeView.razor:

@page "/role-checks-with-authorizeview"

<h3>Role Checks with AuthorizeView</h3>

<AuthorizeView Roles="Admin, SuperUser">
    <p>User: @context.User.Identity?.Name</p>
    <p>You have an 'Admin' or 'SuperUser' role claim.</p>
</AuthorizeView>

<AuthorizeView Roles="Admin">
    <p>User: @context.User.Identity?.Name</p>
    <p>You have the 'Admin' role claim.</p>
    <AuthorizeView Roles="SuperUser" Context="innerContext">
        <p>User: @innerContext.User.Identity?.Name</p>
        <p>You have both 'Admin' and 'SuperUser' role claims.</p>
    </AuthorizeView>
</AuthorizeView>

Předchozí kód vytvoří Context pro vnitřní komponentu AuthorizeView, aby se zabránilo kolizi kontextu AuthenticationState. K AuthenticationState kontextu se přistupuje na vnější straně AuthorizeView pomocí standardního přístupu pro přístup k kontextu (@context.User). Kontext je přístupný ve vnitřním AuthorizeView pomocí pojmenovaného kontextu innerContext (@innerContext.User).

Atribut[Authorize] podporuje autorizaci na základě role pro celé Razor komponenty. AuthorizeAttribute.Roles Použijte parametr. Následující kód omezuje přístup ke komponentě uživatelům, kteří jsou členem Admin této role.

Pages/RequireAdminRoleWithAuthorizeAttribute.razor:

@page "/require-admin-role-with-authorize-attribute"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Roles = "Admin")]

<h1>Require 'Admin' role with [Authorize] attribute</h1>

<p>You can only see this if you're in the 'Admin' role.</p>

Více rolí je možné zadat jako čárkami oddělený seznam. V následujícím příkladu je přístup omezený na uživatele, kteří jsou členy Admin role neboSuperUser role.

Pages/RequireAdminOrSuperUserRoleWithAuthorizeAttribute.razor:

@page "/require-admin-or-superuser-role-with-authorize-attribute"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Roles = "Admin, SuperUser")]

<h1>Require 'Admin' or 'SuperUser' role with [Authorize] attribute</h1>

<p>
    You can only see this if you're in the 'Admin' role or the 'SuperUser' role.
</p>

Při použití více atributů musí být uživatel členem všech zadaných rolí. Následující příklad vyžaduje jakAdminobě roleSuperUser.

Pages/RequireAdminAndSuperUserRolesWithAuthorizeAttributes.razor:

@page "/require-admin-and-superuser-roles-with-authorize-attributes"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Roles = "Admin")]
@attribute [Authorize(Roles = "SuperUser")]

<h1>Require 'Admin' and 'SuperUser' roles with [Authorize] attributes</h1>

<p>
    You can only see this if you're in both the 'Admin' role 
    and the 'SuperUser' role.
</p>

Porovnávání rolí obvykle rozlišuje malá a velká písmena, protože názvy rolí se ukládají a porovnávají pomocí metody porovnání řetězců v rámci .NET. Například Admin (velká A) není považována za stejnou roli jako admin (malá a). Další informace najdete v tématu Claim-based authorization in ASP.NET Core.

Kontroly autorizace založené na zásadách

Požadavky na role se dají vyjádřit pomocí syntaxe zásad, kdy aplikace zaregistruje zásadu při spuštění jako součást konfigurace autorizační služby.

V následujícím příkladu:

  • Zásady RequireAdminRole určují, že uživatelé musí být v Admin roli.
  • Zásady RequireSuperUserRole určují, že uživatelé musí být v SuperUser roli.
builder.Services.AddAuthorizationBuilder()
    .AddPolicy("RequireAdminRole",
         policy => policy.RequireRole("Admin"))
    .AddPolicy("RequireSuperUserRole",
         policy => policy.RequireRole("SuperUser"));
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("RequireAdminRole",
        policy => policy.RequireRole("Admin"));
    options.AddPolicy("RequireSuperUserRole",
        policy => policy.RequireRole("SuperUser"));
});
services.AddAuthorization(options =>
{
    options.AddPolicy("RequireAdminRole",
        policy => policy.RequireRole("Admin"));
    options.AddPolicy("RequireSuperUserRole",
        policy => policy.RequireRole("SuperUser"));
});

Pro autorizaci na zásadách založenou pomocí komponenty použijte parametr AuthorizeView s jedním názvem zásady.

Pages/PassRequireAdminRolePolicy.razor:

@page "/pass-requireadminrole-policy-with-authorizeview"

<h1>Pass 'RequireAdminRole' policy with AuthorizeView</h1>

<AuthorizeView Policy="RequireAdminRole">
    <p>You satisfy the 'RequireAdminRole' policy.</p>
</AuthorizeView>

Pokud chcete vyřešit případ, kdy by měl uživatel splňovat jednu z několika zásad, vytvořte zásadu, která potvrzuje, že uživatel splňuje jiné zásady.

Pokud chcete vyřešit případ, kdy uživatel musí současně splňovat několik zásad, použijte jeden z následujících přístupů:

  • Vytvořte zásadu, AuthorizeView která potvrzuje, že uživatel splňuje několik dalších zásad.

  • Vnořte zásady do více AuthorizeView komponent

    Pages/PassRequireAdminRoleAndRequireSuperUserRolePoliciesWithAuthorizeViews.razor:

    @page "/pass-requireadminrole-and-requiresuperuserrole-policies-with-authorizeviews"
    
    <h1>
        Pass 'RequireAdminRole' and 'RequireSuperUserRole' policies with AuthorizeViews
    </h1>
    
    <AuthorizeView Policy="RequireAdminRole">
        <AuthorizeView Policy="RequireSuperUserRole" Context="innerContext">
            <p>
                You satisfy the 'RequireAdminRole' and 
                'RequireSuperUserRole' policies.
            </p>
        </AuthorizeView>
    </AuthorizeView>
    

Pokud jsou obě Roles i Policy nastavené, autorizace proběhne úspěšně pouze v případě, že jsou splněny obě podmínky. To znamená, že uživatel musí patřit alespoň do jedné ze zadaných rolí a splňovat požadavky definované zásadou.

Pokud není zadán ani Roles ani Policy, AuthorizeView použije výchozí zásadu.

  • Ověření (přihlášení) uživatelé mají oprávnění.
  • Neověření (odhlášení) uživatelé nejsou oprávněni.

Na rozdíl od shody rolí, která obvykle rozlišuje malá a velká písmena, vyhledávání názvů politik v ASP.NET Core obvykle nerozlišuje malá a velká písmena, takže RequireAdminRole a requireadminrole odkazují na stejnou politiku.

Zásady se použijí na celou komponentu Razor pomocí vlastnosti Policy na atributu [Authorize].

Pages/PassRequireAdminRolePolicyWithAuthorizeAttribute.razor:

@page "/pass-requireadminrole-policy-with-authorize-attribute"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "RequireAdminRole")]

<h1>Pass RequireAdminRole policy with [Authorize] attribute</h1>

<p>You can only see this if the 'RequireAdminRole' policy is satisfied.</p>

Pokud chcete v požadavku zadat více povolených rolí, zadejte role jako parametry metody RequireRole . V následujícím příkladu mají uživatelé oprávnění, pokud patří k rolím AdminneboSuperUser rolím:

builder.Services.AddAuthorizationBuilder()
    .AddPolicy("ElevatedRights", policy =>
        policy.RequireRole("Admin", "SuperUser"));
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("ElevatedRights", policy =>
        policy.RequireRole("Admin", "SuperUser"));
});
services.AddAuthorization(options =>
{
    options.AddPolicy("ElevatedRights", policy =>
        policy.RequireRole("Admin", "SuperUser"));
});

Pokud chcete, aby zásady vyžadovaly všechny předchozí role, buď zřetězte role s konfigurátorem zásad, nebo je zadejte do konfigurátoru zásad jednotlivě ve výrazu lambda.

Zavázán konstruktoru zásad:

builder.Services.AddAuthorizationBuilder()
    .AddPolicy("ElevatedRights", policy => 
        policy
            .RequireRole("Admin")
            .RequireRole("SuperUser"));

Alternativně použijte výraz lambda:

builder.Services.AddAuthorizationBuilder()
    .AddPolicy("ElevatedRights",
        policy =>
        {
            policy.RequireRole("Admin");
            policy.RequireRole("SuperUser");
        });
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("ElevatedRights", policy => 
        policy
            .RequireRole("Admin")
            .RequireRole("SuperUser"));
});

Alternativně použijte výraz lambda:

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("ElevatedRights",
        policy =>
        {
            policy.RequireRole("Admin");
            policy.RequireRole("SuperUser");
        });
});
services.AddAuthorization(options =>
{
    options.AddPolicy("ElevatedRights", policy => 
        policy
            .RequireRole("Admin")
            .RequireRole("SuperUser"));
});

Alternativně použijte výraz lambda:

services.AddAuthorization(options =>
{
    options.AddPolicy("ElevatedRights",
        policy =>
        {
            policy.RequireRole("Admin");
            policy.RequireRole("SuperUser");
        });
});

Windows bezpečnostní skupiny pro ověřování jako role aplikace

Jakmile je aplikace konfigurovaná pro ověřování Windows (Blazor-specifické pokyny) s klientem a serverovými počítači ve stejné doméně Windows, skupiny zabezpečení uživatelů se automaticky zahrnou jako nároky v ClaimsPrincipal uživatele.

Po konfiguraci aplikace pro ověřování Windows, kde klientské a serverové stroje jsou součástí stejné domény Windows, se skupiny zabezpečení uživatelů automaticky zahrnou do deklarací identity uživatele v ClaimsPrincipal.

User.Identity je obvykle WindowsIdentity při použití ověřování Windows a můžete načíst nároky skupiny SID nebo zkontrolovat, jestli je uživatel v roli pomocí následujícího kódu, kde zástupný symbol {DOMAIN} je doména a {SID GROUP NAME} je název skupiny SID:

if (User.Identity is WindowsIdentity windowsIdentity)
{
    var groups = windowsIdentity.Groups;

    // If needed, obtain a list of the SID groups
    var securityGroups = 
        groups.Select(g => g.Translate(typeof(NTAccount)).ToString()).ToList();

    // If needed, obtain the user's Windows identity name
    var windowsIdentityName = windowsIdentity.Name;

    // Check if the user is in a specific SID group
    if (User.IsInRole(@"{DOMAIN}\{SID GROUP NAME}"))
    {
        // User is in the specified group
    }
    else
    {
        // User isn't in the specified group
    }
}
else
{
    // The user isn't authenticated with Windows Authentication
}

Ukázku souvisejícího kódu, který přeloží deklarace identity skupiny SID na hodnoty čitelné člověkem v aplikaci Blazor, najdete v UserClaims komponentě v Secure an ASP.NET Core Blazor Web App with Windows Authentication. Takový přístup k načítání deklarací identity skupiny SID lze kombinovat s přidáním deklarací pomocí IClaimsTransformation s cílem vytvořit vlastní deklarace rolí při autentizaci uživatele.

Přístup podobný předchozímu příkladu pro načtení deklarací skupiny SID lze kombinovat s přidáním deklarací pomocí IClaimsTransformation ke vytvoření vlastních deklarací rolí při ověření uživatele.

Dodatečné zdroje