Dela via


Anpassade auktoriseringsprinciper med IAuthorizationRequirementData

IAuthorizationRequirementData Använd gränssnittet för att ange krav som är associerade med auktoriseringsprincipen i attributdefinitioner.

Exempelapp

Det fullständiga exemplet som beskrivs i den här artikeln är exempelappen AuthRequirementsData (dotnet/AspNetCore.Docs.Samples GitHub-lagringsplats) (ladda ned). Exempelappen implementerar en hanterare för lägsta ålder för användare, som kräver att användaren styrker sitt födelsedatum och visar att de är minst 21 år gamla.

Attribut för verifiering av lägsta ålder

Implementeringen MinimumAgeAuthorizeAttribute av IAuthorizationRequirementData anger en auktoriseringsålder:

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;
    }
}

Hanterare för auktorisering av minimiålder

Klassen MinimumAgeAuthorizationHandler hanterar den enda IAuthorizationRequirement som tillhandahålls av MinimumAgeAuthorizeAttribute, enligt den allmänna parametern MinimumAgeAuthorizeAttribute.

HandleRequirementAsync-metoden:

  • Hämtar användarens anspråk på födelsedatum.
  • Hämtar användarens ålder från anspråket.
  • Justerar ålder om användaren inte har haft en födelsedag i år.
  • Markerar att auktoriseringskravet lyckades om användaren uppfyller ålderskravet.
  • Implementerar loggning i demonstrationssyfte.
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 Är registrerad som en begränsad IAuthorizationHandler tjänst i appens Program fil:

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

Visar GreetingsController användarens namn när de uppfyller ålderskravet, vilket innebär en minimiålder på 21 år med [MinimumAgeAuthorize({AGE})] attributet, där {AGE} platshållaren är åldern.

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}!";
}

Om användarens anspråk på födelsedatum anger att de är minst 21 år gamla, visar kontrollern hälsningssträngen och utfärdar statuskoden 200 (OK). Om användaren saknar anspråket på födelsedatum eller om anspråket anger att de inte är minst 21 år gamla visas inte hälsningen och statuskoden 403 (Förbjuden) utfärdas.

JWT-ägarautentiseringstjänster läggs till i appens Program fil:

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

Appinställningsfilen (appsettings.json) konfigurerar målgruppen och utfärdaren för JWT-ägarautentisering:

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

I föregående exempel matchar localhost-målgruppen den localhost-adress som anges i applicationUrl appens startprofil (Properties/launchSettings.json).

Demonstration

Testa provet med dotnet user-jwts och curl.

Från projektets mapp i ett kommandogränssnitt kör du följande kommando för att skapa en JWT-ägartoken med ett födelsedatumanspråk som gör användaren över 21 år gammal:

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

Utdata genererar en token efter "Token:" i kommandogränssnittet:

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}

Spara värdet för token (där {TOKEN} platshållaren visas i föregående utdata) för senare användning.

Du kan avkoda token i en JWT-avkodare online, till exempel jwt.ms för att se dess innehåll, vilket avslöjar att den innehåller ett birthdate anspråk med användarens födelsedatum:

{
  "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]

Kör kommandot igen med ett dateofbirth värde som gör att användaren är under 21 år:

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

Ställ värdet för den andra token åt sidan.

Starta appen i Visual Studio eller med dotnet watch kommandot i .NET CLI.

I .NET CLI kör du följande curl.exe kommando för att begära api/greetings/hello slutpunkten. {TOKEN} Ersätt platshållaren med den första JWT-ägartoken som du sparade tidigare:

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

Utdata indikerar att det lyckades eftersom användarens födelsedatumanspråk anger att de är minst 21 år gamla:

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}!

Loggning anger att ålderskravet uppfylldes:

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

curl.exe Kör kommandot igen med den andra token, vilket anger att användaren är under 21 år. Utdata anger att kravet inte uppfylls. Åtkomst till slutpunkten är förbjuden (statuskod 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