ASP.NET Core 中基于声明的授权Claims-based authorization in ASP.NET Core

本文内容

创建标识后,可以为其分配一个或多个由受信任方颁发的声明。声明是表示使用者的名称值对,而不是主题可执行的操作。例如,你可能有一个由本地驾驶许可证机构颁发的驾照。你的驱动程序许可证有你的出生日期。在这种情况下,声明名称将 DateOfBirth,声明值将是你的出生日期,例如 8th June 1970,颁发者为驾驶许可证授权机构。基于声明的授权最简单的检查声明的值并允许基于该值的资源访问。例如,如果你想要访问晚间俱乐部,授权过程可能是:

门安全官员会评估你的出生日期的价值,以及他们是否信任颁发者(驾驶许可证授权),然后才授予你访问权限。

标识可包含多个值的多个声明,并且可以包含同一类型的多个声明。

添加声明检查Adding claims checks

基于声明的授权检查是声明性的-开发人员将其嵌入到代码中,针对控制器或控制器中的操作,指定当前用户必须拥有的声明,并选择性地指定声明必须持有的值才能访问请求的资源。声明要求基于策略,开发人员必须构建并注册一个表示声明要求的策略。

最简单类型的声明策略将查找声明是否存在,而不检查值。

首先需要构建并注册策略。这会在授权服务配置过程中发生,这通常会在Startup.cs文件中包含 ConfigureServices()

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddControllersWithViews();
  4. services.AddRazorPages();
  5. services.AddAuthorization(options =>
  6. {
  7. options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
  8. });
  9. }
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc();
  4. services.AddAuthorization(options =>
  5. {
  6. options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
  7. });
  8. }

在这种情况下,EmployeeOnly 策略会检查当前标识上是否存在 EmployeeNumber 声明。

然后,使用 AuthorizeAttribute 属性的 Policy 属性来指定策略名称;

  1. [Authorize(Policy = "EmployeeOnly")]
  2. public IActionResult VacationBalance()
  3. {
  4. return View();
  5. }

AuthorizeAttribute 特性可应用于整个控制器,在此实例中,只允许与策略匹配的标识访问控制器上的任何操作。

  1. [Authorize(Policy = "EmployeeOnly")]
  2. public class VacationController : Controller
  3. {
  4. public ActionResult VacationBalance()
  5. {
  6. }
  7. }

如果你的控制器受 AuthorizeAttribute 属性保护,但希望允许匿名访问特定操作,请应用 AllowAnonymousAttribute 属性。

  1. [Authorize(Policy = "EmployeeOnly")]
  2. public class VacationController : Controller
  3. {
  4. public ActionResult VacationBalance()
  5. {
  6. }
  7. [AllowAnonymous]
  8. public ActionResult VacationPolicy()
  9. {
  10. }
  11. }

大多数声明都包含一个值。可以在创建策略时指定允许值的列表。以下示例仅对雇员编号为1、2、3、4或5的雇员成功。

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddControllersWithViews();
  4. services.AddRazorPages();
  5. services.AddAuthorization(options =>
  6. {
  7. options.AddPolicy("Founders", policy =>
  8. policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));
  9. });
  10. }
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc();
  4. services.AddAuthorization(options =>
  5. {
  6. options.AddPolicy("Founders", policy =>
  7. policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));
  8. });
  9. }

添加泛型声明检查Add a generic claim check

如果声明值不是单个值或需要转换,请使用RequireAssertion有关详细信息,请参阅使用 func 来实现策略

多个策略评估Multiple Policy Evaluation

如果将多个策略应用于控制器或操作,则在授予访问权限之前,所有策略都必须通过。例如:

  1. [Authorize(Policy = "EmployeeOnly")]
  2. public class SalaryController : Controller
  3. {
  4. public ActionResult Payslip()
  5. {
  6. }
  7. [Authorize(Policy = "HumanResources")]
  8. public ActionResult UpdateSalary()
  9. {
  10. }
  11. }

在上面的示例中,满足 EmployeeOnly 策略的任何标识都可以访问 Payslip 操作,因为该策略是在控制器上强制实施的。但是,若要调用 UpdateSalary 操作,标识必须同时满足 EmployeeOnly 策略和 HumanResources 策略。

如果需要更复杂的策略,例如拍摄一个出生日期、计算该日期的年龄,然后检查年龄是否为21或更低,则需要编写自定义策略处理程序