Autorização baseada em função no ASP.NET Core

Quando uma identidade é criada, ela pode pertencer a uma ou mais funções. Por exemplo, Tracy pode pertencer a Administrator e User papéis, enquanto Scott só pode pertencer ao User papel. A forma como essas funções são criadas e gerenciadas depende do repositório de suporte do processo de autorização. As funções são expostas ao desenvolvedor por meio do IsInRole método na ClaimsPrincipal classe. AddRoles deve ser adicionado aos serviços de função.

Embora as funções sejam declarações, nem todas as declarações são funções. Dependendo do emissor de identidade, uma função pode ser uma coleção de usuários que podem aplicar declarações para membros do grupo, bem como uma declaração real sobre uma identidade. No entanto, as declarações devem ser informações sobre um usuário individual. Usar funções para adicionar declarações a um usuário pode confundir o limite entre o usuário e suas declarações individuais. Essa confusão é a razão pela qual os modelos de SPA não são projetados em torno de funções. Além disso, para as organizações que migram de um sistema herdado local, a proliferação de funções ao longo dos anos pode significar que uma declaração de função pode ser muito grande para ser contida em um token utilizável por SPAs. Para proteger os SPAs, consulte Introdução à autenticação para Aplicativos de Página Única no ASP.NET Core.

Adicionar serviços de função a Identity

Registre serviços de autorização baseados em Program.cs função chamando AddRoles com o tipo de função na configuração do Identity aplicativo. O tipo de função no exemplo a seguir é IdentityRole:

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

Adicionando verificações de função

Verificações de autorização baseada em função:

  • São declarativas e especificam funções das quais o usuário atual deve ser membro para acessar o recurso solicitado.
  • São aplicadas a Razor páginas, controladores ou ações dentro de um controlador.
  • Não é possível aplicar no nível do Razor manipulador de página, eles devem ser aplicados à Página.

Por exemplo, o código a seguir limita o acesso a todas as AdministrationController ações dos usuários que são membros da Administrator função:

[Authorize(Roles = "Administrator")]
public class AdministrationController : Controller
{
    public IActionResult Index() =>
        Content("Administrator");
}

Várias funções podem ser especificadas como uma lista separada por vírgulas:

[Authorize(Roles = "HRManager,Finance")]
public class SalaryController : Controller
{
    public IActionResult Payslip() =>
                    Content("HRManager || Finance");
}

SalaryController é acessível por usuários que são membros da HRManager função ou da Finance função.

Quando vários atributos são aplicados, um usuário de acesso deve ser um membro de todas as funções especificadas. O exemplo a seguir exige que um usuário seja membro dafunção eControlPanelUser do PowerUser usuário:

[Authorize(Roles = "PowerUser")]
[Authorize(Roles = "ControlPanelUser")]
public class ControlPanelController : Controller
{
    public IActionResult Index() =>
        Content("PowerUser && ControlPanelUser");
}

O acesso a uma ação pode ser limitado aplicando atributos adicionais de autorização de função no nível da ação:

[Authorize(Roles = "Administrator, PowerUser")]
public class ControlAllPanelController : Controller
{
    public IActionResult SetTime() =>
        Content("Administrator || PowerUser");

    [Authorize(Roles = "Administrator")]
    public IActionResult ShutDown() =>
        Content("Administrator only");
}

No controlador anterior ControlAllPanelController :

  • Os membros da Administrator função ou da PowerUser função podem acessar o controlador e a ação SetTime .
  • Somente membros da Administrator função podem acessar a ação ShutDown .

Um controlador pode ser bloqueado, mas permitir acesso anônimo e não autenticado a ações individuais:

[Authorize]
public class Control3PanelController : Controller
{
    public IActionResult SetTime() =>
        Content("[Authorize]");

    [AllowAnonymous]
    public IActionResult Login() =>
        Content("[AllowAnonymous]");
}

Para Razor Páginas, [Authorize] pode ser aplicado por:

[Authorize(Policy = "RequireAdministratorRole")]
public class UpdateModel : PageModel
{
    public IActionResult OnPost() =>
         Content("OnPost RequireAdministratorRole");
}

Importante

Os atributos de filtro, incluindo AuthorizeAttribute, só podem ser aplicados ao PageModel e não podem ser aplicados a métodos específicos do manipulador de página.

Verificações de função baseadas em política

Os requisitos de função também podem ser expressos usando a sintaxe Política, em que um desenvolvedor registra uma política na inicialização do aplicativo como parte da configuração do serviço de autorização. Normalmente, isso ocorre no Program.cs arquivo:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("RequireAdministratorRole",
         policy => policy.RequireRole("Administrator"));
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthentication();
app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

As políticas são aplicadas usando a Policy propriedade no [Authorize] atributo:

[Authorize(Policy = "RequireAdministratorRole")]
public IActionResult Shutdown()
{
    return View();
}

Para especificar várias funções permitidas em um requisito, especifique-as como parâmetros para o RequireRole método:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("ElevatedRights", policy =>
          policy.RequireRole("Administrator", "PowerUser", "BackupAdministrator"));
});

var app = builder.Build();

O código anterior autoriza os usuários que pertencem às AdministratorPowerUser funções ou BackupAdministrator às funções.

Quando uma identidade é criada, ela pode pertencer a uma ou mais funções. Por exemplo, Tracy pode pertencer às funções administrador e usuário, enquanto Scott pode pertencer apenas à função usuário. A forma como essas funções são criadas e gerenciadas depende do repositório de suporte do processo de autorização. As funções são expostas ao desenvolvedor por meio do IsInRole método na ClaimsPrincipal classe.

É recomendável não usar funções como declarações, mas sim usar uma declaração. Ao usar aplicativos de página única (SPAs), consulte Introdução à autenticação para aplicativos de página única no ASP.NET Core.

Adicionando verificações de função

Verificações de autorização baseada em função:

  • São declarativos.
  • São aplicadas a Razor páginas, controladores ou ações dentro de um controlador.
  • Não é possível aplicar no nível do Razor manipulador de página, eles devem ser aplicados à Página.

Verificações de autorização baseadas em função especificam quais funções o usuário atual deve ser membro para acessar o recurso solicitado.

Por exemplo, o código a seguir limita o acesso a todas as AdministrationController ações dos usuários que são membros da Administrator função:

[Authorize(Roles = "Administrator")]
public class AdministrationController : Controller
{
    public IActionResult Index() =>
        Content("Administrator");
}

Várias funções podem ser especificadas como uma lista separada por vírgulas:

[Authorize(Roles = "HRManager,Finance")]
public class SalaryController : Controller
{
    public IActionResult Payslip() =>
                    Content("HRManager || Finance");
}

O controlador SalaryController só é acessível por usuários que são membros da HRManager função ou da Finance função.

Se você aplicar vários atributos, um usuário de acesso deverá ser membro de todas as funções especificadas. O exemplo a seguir exige que um usuário seja membro da função e ControlPanelUser do PowerUser usuário:

[Authorize(Roles = "PowerUser")]
[Authorize(Roles = "ControlPanelUser")]
public class ControlPanelController : Controller
{
    public IActionResult Index() =>
        Content("PowerUser && ControlPanelUser");
}

Você pode limitar ainda mais o acesso aplicando atributos adicionais de autorização de função no nível da ação:

[Authorize(Roles = "Administrator, PowerUser")]
public class ControlAllPanelController : Controller
{
    public IActionResult SetTime() =>
        Content("Administrator || PowerUser");

    [Authorize(Roles = "Administrator")]
    public IActionResult ShutDown() =>
        Content("Administrator only");
}

No controlador anterior ControlAllPanelController :

  • Os membros da Administrator função ou da PowerUser função podem acessar o controlador e a ação SetTime .
  • Somente membros da Administrator função podem acessar a ação ShutDown .

Você também pode bloquear um controlador, mas permitir acesso anônimo e não autenticado a ações individuais.

[Authorize]
public class Control3PanelController : Controller
{
    public IActionResult SetTime() =>
        Content("[Authorize]");

    [AllowAnonymous]
    public IActionResult Login() =>
        Content("[AllowAnonymous]");
}

Para Razor Páginas, o [Authorize] código pode ser aplicado por:

[Authorize(Policy = "RequireAdministratorRole")]
public class UpdateModel : PageModel
{
    public ActionResult OnPost()
    {
    }
}

Importante

Os atributos de filtro, incluindo AuthorizeAttribute, só podem ser aplicados ao PageModel e não podem ser aplicados a métodos específicos do manipulador de página.

Verificações de função baseadas em política

Os requisitos de função também podem ser expressos usando a nova sintaxe de Política, em que um desenvolvedor registra uma política na inicialização como parte da configuração do serviço de autorização. Normalmente, isso ocorre em ConfigureServices() seu Startup.cs arquivo.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();

    services.AddAuthorization(options =>
    {
        options.AddPolicy("RequireAdministratorRole",
             policy => policy.RequireRole("Administrator"));
    });
}

As políticas são aplicadas usando a Policy propriedade no [Authorize]atributo:

[Authorize(Policy = "RequireAdministratorRole")]
public IActionResult Shutdown()
{
    return View();
}

Se você quiser especificar várias funções permitidas em um requisito, poderá especificá-las como parâmetros para o RequireRole método:

options.AddPolicy("ElevatedRights", policy =>
                  policy.RequireRole("Administrator", "PowerUser", "BackupAdministrator"));

Este exemplo autoriza os usuários que pertencem às AdministratorPowerUser funções.BackupAdministrator

Adicionar serviços de função a Identity

Acrescente AddRoles para adicionar serviços de função:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>()
        .AddRoles<IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddControllersWithViews();
    services.AddRazorPages();
}