使用 自訂授權原則
使用此 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