共用方式為


使用 自訂授權原則 IAuthorizationRequirementData

使用此 IAuthorizationRequirementData 介面,在屬性定義中指定授權原則相關聯的需求。

範例應用程式

本文所述的完整範例是 AuthRequirementsData 範例應用程式 (GitHub 存放庫) (dotnet/AspNetCore.Docs.Samples如何下載)。 範例應用程式會為用戶實作最低年齡處理程式,要求使用者出示出生日期宣告,指出他們至少 21 歲。

最小年齡授權屬性

MinimumAgeAuthorizeAttribute 實作 IAuthorizationRequirementData 會設定授權存留期:

using Microsoft.AspNetCore.Authorization;

namespace AuthRequirementsData.Authorization;

class MinimumAgeAuthorizeAttribute(int age) : AuthorizeAttribute, 
    IAuthorizationRequirement, IAuthorizationRequirementData
{
    public int Age { get; set; } = age;

    public IEnumerable<IAuthorizationRequirement> GetRequirements()
    {
        yield return this;
    }
}

最小存留期授權處理程式

MinimumAgeAuthorizationHandler 類別會根據泛型參數 IAuthorizationRequirement 所指定,處理由 MinimumAgeAuthorizeAttribute 提供的單一 MinimumAgeAuthorizeAttribute

HandleRequirementAsync 方法:

  • 取得使用者的出生日期宣告。
  • 從權利要求中獲取用戶的年齡。
  • 如果使用者今年還沒有過生日,請調整年齡。
  • 如果使用者符合年齡需求,則標示授權需求成功。
  • 實現記錄以供示範之用。
using System.Globalization;
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;

namespace AuthRequirementsData.Authorization;

class MinimumAgeAuthorizationHandler(ILogger<MinimumAgeAuthorizationHandler> logger) 
    : AuthorizationHandler<MinimumAgeAuthorizeAttribute>
{
    // Check whether a given minimum age requirement is satisfied.
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context, 
        MinimumAgeAuthorizeAttribute requirement)
    {
        logger.LogInformation(
            "Evaluating authorization requirement for age >= {age}", 
            requirement.Age);

        // Get the user's birth date claim.
        var dateOfBirthClaim = 
            context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth);

        if (dateOfBirthClaim != null)
        {
            // If the user has a date of birth claim, obtain their age.
            var dateOfBirth = Convert.ToDateTime(dateOfBirthClaim.Value, 
                CultureInfo.InvariantCulture);
            var age = DateTime.Now.Year - dateOfBirth.Year;

            // Adjust age if the user hasn't had a birthday yet this year.
            if (dateOfBirth > DateTime.Now.AddYears(-age))
            {
                age--;
            }

            // If the user meets the age requirement, mark the authorization
            // requirement succeeded.
            if (age >= requirement.Age)
            {
                logger.LogInformation(
                    "Minimum age authorization requirement {age} satisfied", 
                    requirement.Age);
                context.Succeed(requirement);
            }
            else
            {
                logger.LogInformation(
                    "Current user's DateOfBirth claim ({dateOfBirth}) doesn't " +
                    "satisfy the minimum age authorization requirement {age}",
                    dateOfBirthClaim.Value,
                    requirement.Age);
            }
        }
        else
        {
            logger.LogInformation("No DateOfBirth claim present");
        }

        return Task.CompletedTask;
    }
}

MinimumAgeAuthorizationHandler在應用程式的IAuthorizationHandler檔案中被註冊為單例Program服務:

builder.Services.AddSingleton<IAuthorizationHandler,
    MinimumAgeAuthorizationHandler>();

當用戶滿足最低年齡政策時,GreetingsController 會顯示用戶的名稱,並使用與 [MinimumAgeAuthorize({AGE})] 屬性相結合的 21 歲年齡,其中 {AGE} 佔位符為年齡:

using Microsoft.AspNetCore.Mvc;
using AuthRequirementsData.Authorization;

namespace AuthRequirementsData.Controllers;

[ApiController]
[Route("api/[controller]")]
public class GreetingsController : Controller
{
    [MinimumAgeAuthorize(21)]
    [HttpGet("hello")]
    public string Hello() => 
        $"Hello {HttpContext.User.Identity?.Name}!";
}

如果使用者的出生日期宣告指出他們至少 21 歲,控制器會顯示問候字串,併發出 200 (OK) 狀態代碼。 如果使用者缺少出生日期宣告或宣告指出他們未滿 21 歲,則不會顯示問候語,並發出 403(禁止)狀態代碼。

JWT 持有人驗證服務會在應用程式的 Program 檔案中新增:

builder.Services.AddAuthentication().AddJwtBearer();

應用程式設定檔案(appsettings.json)會設定 JWT 持有者驗證的受眾和簽發者:

"Authentication": {
  "Schemes": {
    "Bearer": {
      "ValidAudiences": [
        "https://localhost:51100"
      ],
      "ValidIssuer": "dotnet-user-jwts"
    }
  }
}

在上述範例中,localhost 受眾會匹配應用程式啟動配置檔(applicationUrl)中由Properties/launchSettings.json指定的 localhost 位址。

示範

使用 dotnet user-jwts 和 curl 測試範例。

從專案資料夾內的命令殼層中,執行下列命令以建立一個包含出生日期宣告的 JWT 持有人令牌,使該使用者超過 21 歲:

dotnet user-jwts create --claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth=1989-01-01

輸出會在命令提示字元中的「Token:」之後產生令牌:

New JWT saved with ID '{JWT ID}'.
Name: {USER}
Custom Claims: [http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth=1989-01-01]

Token: {TOKEN}

將標記的值({TOKEN} 佔位符出現在上面的輸出中)存放起來,以便稍後使用。

您可以在線上 JWT 解碼器中解碼令牌,例如使用 jwt.ms 來查看其內容,顯示其中包含使用者出生日期的 birthdate 宣告。

{
  "alg": "HS256",
  "typ": "JWT"
}.{
  "unique_name": "{USER}",
  "sub": "{USER}",
  "jti": "{JWT ID}",
  "birthdate": "1989-01-01",
  "aud": [
    "https://localhost:51100",
    "http://localhost:51101"
  ],
  "nbf": 1747315312,
  "exp": 1755264112,
  "iat": 1747315313,
  "iss": "dotnet-user-jwts"
}.[Signature]

以值 dateofbirth 再次執行 命令,讓用戶年齡在21歲以下:

dotnet user-jwts create --claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth=2020-01-01

將第二個令牌的值設置在一旁。

在 Visual Studio 中啟動應用程式,或使用 .NET CLI 的 dotnet watch 命令啟動應用程式。

在 .NET CLI 中,執行下列 curl.exe 命令來要求 api/greetings/hello 端點。 將 {TOKEN} 佔位符替換成您先前儲存的第一個 JWT 承載令牌。

curl.exe -i -H "Authorization: Bearer {TOKEN}" https://localhost:51100/api/greetings/hello

輸出表示成功,因為使用者的出生日期宣告指出他們至少 21 歲:

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Thu, 15 May 2025 22:58:10 GMT
Server: Kestrel
Transfer-Encoding: chunked

Hello {USER}!

記錄表示符合年齡需求:

MinimumAgeAuthorizationHandler: Information: Evaluating authorization requirement for age >= 21
MinimumAgeAuthorizationHandler: Information: Minimum age authorization requirement 21 satisfied

使用第二個令牌重新執行 curl.exe 命令,指出用戶年齡在 21 歲以下。 輸出表示不符合需求。 禁止存取端點 (狀態代碼 403):

HTTP/1.1 403 Forbidden
Content-Length: 0
Date: Thu, 15 May 2025 22:58:36 GMT
Server: Kestrel

MinimumAgeAuthorizationHandler: Information: Evaluating authorization requirement for age >= 21
MinimumAgeAuthorizationHandler: Information: Current user's DateOfBirth claim (2020-01-01) doesn't satisfy the minimum age authorization requirement 21