ASP.NET Core 中的宣告型授權

建立身分識別時,可能會指派信任方發出的一個或多個宣告。 宣告是成對的名稱和數值,代表主體的身分,而不是主體可以執行的動作。 例如,您可能擁有由當地駕駛執照授權機構簽發的駕照。 您的駕駛執照有您的出生日期。 在此情況下,宣告名稱會是 DateOfBirth,宣告值會是您的出生日期,例如 8th June 1970,簽發者會是駕駛執照授權單位。 宣告型授權最簡單,會檢查宣告的值,並允許根據該值存取資源。 例如,如果您想要進入夜總會,授權程序可能是:

大門保安人員讓您入場之前,會先評估出生日期宣告的值,以及他們是否信任簽發者 (駕駛執照授權單位)。

身分識別可以包含具有多個值的多個宣告,而且可以包含相同類型的多個宣告。

新增宣告檢查

宣告型授權檢查:

  • 為宣告式。
  • 會套用至控制器內的 Razor Pages、控制器或動作。
  • 無法在 Razor Page 處理常式層級套用,必須套用至 Page。

程式碼中的宣告會指定目前使用者必須擁有的宣告,並選擇性地指定宣告必須保留的值來存取要求的資源。 宣告需求是以原則為基礎;開發人員必須建置並註冊表示宣告需求的原則。

最簡單的宣告原則類型會尋找宣告是否存在,而且不會檢查其值。

建置和註冊原則並呼叫 UseAuthorization。 註冊原則是授權服務組態的一部分,通常是在 Program.cs 檔案中:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddAuthorization(options =>
{
   options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
});

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();

在此情況下,EmployeeOnly 原則會檢查目前身分識別上是否有 EmployeeNumber 宣告。

使用 屬性上的 [Authorize] 屬性來套用 Policy 原則,以指定原則名稱。

[Authorize(Policy = "EmployeeOnly")]
public IActionResult VacationBalance()
{
    return View();
}

屬性 [Authorize] 可以套用至整個控制器或 Razor Page,在此情況下,只有符合原則的身分識別才能存取控制器上的任何動作。

[Authorize(Policy = "EmployeeOnly")]
public class VacationController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    public ActionResult VacationBalance()
    {
        return View();
    }

    [AllowAnonymous]
    public ActionResult VacationPolicy()
    {
        return View();
    }
}

下列程式碼會將 [Authorize] 屬性套用至 Razor Page:

[Authorize(Policy = "EmployeeOnly")]
public class IndexModel : PageModel
{
    public void OnGet()
    {

    }
}

原則無法在 Razor 頁面處理常式層級套用,必須將原則套用至 Page。

如果您有受 屬性保護但 [Authorize] 想要允許匿名存取特定動作的控制器,您可以套用 AllowAnonymousAttribute 屬性。

[Authorize(Policy = "EmployeeOnly")]
public class VacationController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    public ActionResult VacationBalance()
    {
        return View();
    }

    [AllowAnonymous]
    public ActionResult VacationPolicy()
    {
        return View();
    }
}

由於原則無法套用至 Razor Page 處理常式層級,因此當原則必須在頁面處理常式層級套用時,建議您使用控制器。 Razor Page 處理常式層級不需要原則的其餘應用程式可以使用 Razor Pages。

大部分的宣告都會有值。 您可以在建立原則時指定允許值的清單。 下列範例只會針對員工編號為 1、2、3、4 或 5 的員工成功。

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("Founders", policy =>
                      policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));
});

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();

新增泛型宣告檢查

如果宣告值不是單一值,或需要轉換,請使用 RequireAssertion。 如需詳細資訊,請參閱使用 func 來完成原則

多重原則評估

如果在控制器和動作層級套用多個原則,所有原則都必須通過,才能授予存取權:

[Authorize(Policy = "EmployeeOnly")]
public class SalaryController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    public IActionResult Payslip()
    {
        return View();
    }

    [Authorize(Policy = "HumanResources")]
    public IActionResult UpdateSalary()
    {
        return View();
    }
}

在上述範例中,任何滿足 EmployeeOnly 原則的身分識別,都可以在控制器上強制執行該原則時存取 Payslip 動作。 不過,若要呼叫 UpdateSalary 動作,身分識別必須同時滿足 EmployeeOnly 原則和原則。 HumanResources

如果您想要更複雜的原則,例如取得出生日期、計算年齡,然後檢查年齡是否為 21 歲或更舊,則需要撰寫 自訂原則處理常式

在下列範例中,這兩個頁面處理常式方法都必須同時滿足 EmployeeOnly 原則和 HumanResources 原則:

[Authorize(Policy = "EmployeeOnly")]
[Authorize(Policy = "HumanResources")]
public class SalaryModel : PageModel
{
    public ContentResult OnGetPayStub()
    {
        return Content("OnGetPayStub");
    }

    public ContentResult OnGetSalary()
    {
        return Content("OnGetSalary");
    }
}

建立身分識別時,可能會指派信任方發出的一個或多個宣告。 宣告是成對的名稱和數值,代表主體的身分,而不是主體可以執行的動作。 例如,您可能擁有由當地駕駛執照授權機構簽發的駕照。 您的駕駛執照有您的出生日期。 在此情況下,宣告名稱會是 DateOfBirth,宣告值會是您的出生日期,例如 8th June 1970,簽發者會是駕駛執照授權單位。 宣告型授權最簡單,會檢查宣告的值,並允許根據該值存取資源。 例如,如果您想要進入夜總會,授權程序可能是:

大門保安人員讓您入場之前,會先評估出生日期宣告的值,以及他們是否信任簽發者 (駕駛執照授權單位)。

身分識別可以包含具有多個值的多個宣告,而且可以包含相同類型的多個宣告。

新增宣告檢查

宣告型授權檢查是宣告式的 - 開發人員會將其內嵌在其程式碼中、針對控制器內的控制器或動作、指定目前使用者必須擁有的宣告,以及宣告必須保留的值,以存取要求的資源。 宣告需求屬於原則型,開發人員必須建置並註冊表示宣告需求的原則。

最簡單的宣告原則類型會尋找宣告是否存在,而且不會檢查其值。

建置並註冊原則。 這會作為授權服務組態的一部分進行,這通常會在您的 Startup.cs 檔案中參與 ConfigureServices()

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

    services.AddAuthorization(options =>
    {
        options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
    });
}

Configure 中呼叫 UseAuthorization。 下列程式碼是由 ASP.NET Core Web 應用程式範本所產生:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseMigrationsEndPoint();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

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

    app.UseRouting();

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

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

在此情況下,EmployeeOnly 原則會檢查目前身分識別上是否有 EmployeeNumber 宣告。

接著,您可以使用 [Authorize] 屬性上的 Policy 屬性來套用原則,以指定原則名稱;

[Authorize(Policy = "EmployeeOnly")]
public IActionResult VacationBalance()
{
    return View();
}

[Authorize] 屬性可以套用至整個控制器,在此實例中,只有符合原則的身分識別才能存取控制器上的任何動作。

[Authorize(Policy = "EmployeeOnly")]
public class VacationController : Controller
{
    public ActionResult VacationBalance()
    {
    }
}

如果您有受 [Authorize] 屬性保護的控制器,但想要允許匿名存取您套用 AllowAnonymousAttribute 屬性的特定動作。

[Authorize(Policy = "EmployeeOnly")]
public class VacationController : Controller
{
    public ActionResult VacationBalance()
    {
    }

    [AllowAnonymous]
    public ActionResult VacationPolicy()
    {
    }
}

大部分的宣告都會有值。 您可以在建立原則時指定允許值的清單。 下列範例只針對員工號碼為 1、2、3、4 或 5 的員工會成功。

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

    services.AddAuthorization(options =>
    {
        options.AddPolicy("Founders", policy =>
                          policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));
    });
}

新增泛型宣告檢查

如果宣告值不是單一值,或需要轉換,請使用 RequireAssertion。 如需詳細資訊,請參閱使用 func 來完成原則

多重原則評估

如果您將多個原則套用至控制器或動作,則所有原則都必須通過,才能授予存取權。 例如:

[Authorize(Policy = "EmployeeOnly")]
public class SalaryController : Controller
{
    public ActionResult Payslip()
    {
    }

    [Authorize(Policy = "HumanResources")]
    public ActionResult UpdateSalary()
    {
    }
}

在上述範例中,任何滿足 EmployeeOnly 原則的身分識別都可以在控制器上強制執行該原則時存取 Payslip 動作。 不過,若要呼叫 UpdateSalary 動作,身分識別必須同時滿足 EmployeeOnly 原則和 HumanResources 原則。

如果您想要更複雜的原則,例如取得出生日期宣告、計算年齡,然後檢查年齡為 21 歲或更大,則您需要撰寫自訂原則處理常式

建立身分識別時,可能會指派信任方發出的一個或多個宣告。 宣告是成對的名稱和數值,代表主體的身分,而不是主體可以執行的動作。 例如,您可能擁有由當地駕駛執照授權機構簽發的駕照。 您的駕駛執照有您的出生日期。 在此情況下,宣告名稱會是 DateOfBirth,宣告值會是您的出生日期,例如 8th June 1970,簽發者會是駕駛執照授權單位。 宣告型授權最簡單,會檢查宣告的值,並允許根據該值存取資源。 例如,如果您想要進入夜總會,授權程序可能是:

大門保安人員讓您入場之前,會先評估出生日期宣告的值,以及他們是否信任簽發者 (駕駛執照授權單位)。

身分識別可以包含具有多個值的多個宣告,而且可以包含相同類型的多個宣告。

新增宣告檢查

宣告型授權檢查是宣告式的 - 開發人員會將其內嵌在其程式碼中、針對控制器內的控制器或動作、指定目前使用者必須擁有的宣告,以及宣告必須保留的值,以存取要求的資源。 宣告需求屬於原則型,開發人員必須建置並註冊表示宣告需求的原則。

最簡單的宣告原則類型會尋找宣告是否存在,而且不會檢查其值。

建置並註冊原則。 這會作為授權服務組態的一部分進行,這通常會在您的 Startup.cs 檔案中參與 ConfigureServices()

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

    services.AddAuthorization(options =>
    {
        options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
    });
}

在此情況下,EmployeeOnly 原則會檢查目前身分識別上是否有 EmployeeNumber 宣告。

接著,您可以使用 [Authorize] 屬性上的 Policy 屬性來套用原則,以指定原則名稱;

[Authorize(Policy = "EmployeeOnly")]
public IActionResult VacationBalance()
{
    return View();
}

[Authorize] 屬性可以套用至整個控制器,在此實例中,只有符合原則的身分識別才能存取控制器上的任何動作。

[Authorize(Policy = "EmployeeOnly")]
public class VacationController : Controller
{
    public ActionResult VacationBalance()
    {
    }
}

如果您有受 [Authorize] 屬性保護的控制器,但想要允許匿名存取您套用 AllowAnonymousAttribute 屬性的特定動作。

[Authorize(Policy = "EmployeeOnly")]
public class VacationController : Controller
{
    public ActionResult VacationBalance()
    {
    }

    [AllowAnonymous]
    public ActionResult VacationPolicy()
    {
    }
}

大部分的宣告都會有值。 您可以在建立原則時指定允許值的清單。 下列範例只針對員工號碼為 1、2、3、4 或 5 的員工會成功。

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

    services.AddAuthorization(options =>
    {
        options.AddPolicy("Founders", policy =>
                          policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));
    });
}

新增泛型宣告檢查

如果宣告值不是單一值,或需要轉換,請使用 RequireAssertion。 如需詳細資訊,請參閱使用 func 來完成原則

多重原則評估

如果您將多個原則套用至控制器或動作,則所有原則都必須通過,才能授予存取權。 例如:

[Authorize(Policy = "EmployeeOnly")]
public class SalaryController : Controller
{
    public ActionResult Payslip()
    {
    }

    [Authorize(Policy = "HumanResources")]
    public ActionResult UpdateSalary()
    {
    }
}

在上述範例中,任何滿足 EmployeeOnly 原則的身分識別都可以在控制器上強制執行該原則時存取 Payslip 動作。 不過,若要呼叫 UpdateSalary 動作,身分識別必須同時滿足 EmployeeOnly 原則和 HumanResources 原則。

如果您想要更複雜的原則,例如取得出生日期宣告、計算年齡,然後檢查年齡為 21 歲或更大,則您需要撰寫自訂原則處理常式