ASP.NET Core 中的基于角色的授权Role-based authorization in ASP.NET Core

创建标识时,它可能属于一个或多个角色。When an identity is created it may belong to one or more roles. 例如,Tracy 可能属于管理员角色和用户角色,但 Scott 可能只属于用户角色。For example, Tracy may belong to the Administrator and User roles whilst Scott may only belong to the User role. 如何创建和管理这些角色取决于授权过程的后备存储。How these roles are created and managed depends on the backing store of the authorization process. 角色通过ClaimsPrincipal类的IsInRole方法向开发人员公开。Roles are exposed to the developer through the IsInRole method on the ClaimsPrincipal class.

添加角色检查Adding role checks

基于角色的授权检查是声明性—开发人员将其嵌入到代码中,针对控制器或控制器中的操作,指定当前用户必须是其成员的角色才能访问请求的资源。Role-based authorization checks are declarative—the developer embeds them within their code, against a controller or an action within a controller, specifying roles which the current user must be a member of to access the requested resource.

例如,以下代码将对 AdministrationController 上的任何操作的访问权限限制为作为 Administrator 角色成员的用户:For example, the following code limits access to any actions on the AdministrationController to users who are a member of the Administrator role:

[Authorize(Roles = "Administrator")]
public class AdministrationController : Controller
{
}

可以将多个角色指定为逗号分隔列表:You can specify multiple roles as a comma separated list:

[Authorize(Roles = "HRManager,Finance")]
public class SalaryController : Controller
{
}

只有作为 HRManager 角色成员的用户或 Finance 角色的成员才能访问此控制器。This controller would be only accessible by users who are members of the HRManager role or the Finance role.

如果应用多个属性,则访问用户必须是所有指定角色的成员;下面的示例要求用户必须同时是 PowerUserControlPanelUser 角色的成员。If you apply multiple attributes then an accessing user must be a member of all the roles specified; the following sample requires that a user must be a member of both the PowerUser and ControlPanelUser role.

[Authorize(Roles = "PowerUser")]
[Authorize(Roles = "ControlPanelUser")]
public class ControlPanelController : Controller
{
}

您可以通过在操作级别应用其他角色授权属性来进一步限制访问权限:You can further limit access by applying additional role authorization attributes at the action level:

[Authorize(Roles = "Administrator, PowerUser")]
public class ControlPanelController : Controller
{
    public ActionResult SetTime()
    {
    }

    [Authorize(Roles = "Administrator")]
    public ActionResult ShutDown()
    {
    }
}

在前面的代码片段中,Administrator 角色或 PowerUser 角色的成员可以访问控制器和 SetTime 操作,但只有 Administrator 角色的成员才能访问 ShutDown 操作。In the previous code snippet members of the Administrator role or the PowerUser role can access the controller and the SetTime action, but only members of the Administrator role can access the ShutDown action.

你还可以锁定控制器,但允许对单个操作进行匿名、未经身份验证的访问。You can also lock down a controller but allow anonymous, unauthenticated access to individual actions.

[Authorize]
public class ControlPanelController : Controller
{
    public ActionResult SetTime()
    {
    }

    [AllowAnonymous]
    public ActionResult Login()
    {
    }
}

对于 Razor Pages,可以通过以下任一方法应用 AuthorizeAttributeFor Razor Pages, the AuthorizeAttribute can be applied by either:

  • 使用约定,或Using a convention, or
  • AuthorizeAttribute 应用到 PageModel 实例:Applying the AuthorizeAttribute to the PageModel instance:
[Authorize(Policy = "RequireAdministratorRole")]
public class UpdateModel : PageModel
{
    public ActionResult OnPost()
    {
    }
}

重要

筛选器属性(包括 AuthorizeAttribute)只能应用于 PageModel,而不能应用于特定页面处理程序方法。Filter attributes, including AuthorizeAttribute, can only be applied to PageModel and cannot be applied to specific page handler methods.

基于策略的角色检查Policy based role checks

还可以使用新策略语法来表示角色要求,开发人员可在其中将在启动时作为授权服务配置的一部分注册策略。Role requirements can also be expressed using the new Policy syntax, where a developer registers a policy at startup as part of the Authorization service configuration. 这通常出现在Startup.cs文件 ConfigureServices() 中。This normally occurs in ConfigureServices() in your Startup.cs file.

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

    services.AddAuthorization(options =>
    {
        options.AddPolicy("RequireAdministratorRole",
             policy => policy.RequireRole("Administrator"));
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

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

使用 AuthorizeAttribute 属性上的 Policy 属性应用策略:Policies are applied using the Policy property on the AuthorizeAttribute attribute:

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

如果要在某个要求中指定多个允许的角色,则可以将它们指定为 RequireRole 方法的参数:If you want to specify multiple allowed roles in a requirement then you can specify them as parameters to the RequireRole method:

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

此示例授权属于 AdministratorPowerUserBackupAdministrator 角色的用户。This example authorizes users who belong to the Administrator, PowerUser or BackupAdministrator roles.

将角色服务添加到标识Add Role services to Identity

追加AddRoles以添加角色服务:Append AddRoles to add Role services:

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();
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>()
        .AddRoles<IdentityRole>()
        .AddDefaultUI(UIFramework.Bootstrap4)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}