如何限制对用户属性的页面访问

How do I restrict page access on user properties

我有一个 blazor 页面,我需要按年龄限制访问。我正在使用托管的 webassembly。我想使用 [Authorize] 属性,但我不知道如何让它在从出生日期开始的计算中起作用。我正在以 DateTimeOffset 格式存储出生日期。

首先,您需要对 Dob 提出索赔。我不确定您是否应该使用 JwtClaimTypes.BirthDate,因为您的日期时间格式与此处预期的格式不同。

 public class CustomUserClaimsPrincipalFactory
         : UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>
    {
        public CustomUserClaimsPrincipalFactory(
            UserManager<ApplicationUser> userManager,
            RoleManager<IdentityRole> roleManager,
            IOptions<IdentityOptions> optionsAccessor)
            : base(userManager, roleManager, optionsAccessor)
        { }

        public override async Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
        {
            ClaimsPrincipal principal = await base.CreateAsync(user);
            var identity = (ClaimsIdentity)principal.Identity;

            var claims = new List<Claim>
            {
                new Claim(JwtClaimTypes.BirthDate, JsonSerializer.Serialize(user.DoB))
            };
...
            identity.AddClaims(claims);
            return principal;
        }
    }

要使用它,请将此行添加到服务器代码startup.cs

services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
               .AddEntityFrameworkStores<ApplicationDbContext>()
               .AddClaimsPrincipalFactory<CustomUserClaimsPrincipalFactory>();

您还需要确保将声明添加到 JWT,以便客户端可以看到它。

 services.AddIdentityServer()
                .AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
                {
                    const string OpenId = "openid";

                    options.IdentityResources[OpenId].UserClaims.Add(JwtClaimTypes.BirthDate);
                    options.ApiResources.Single().UserClaims.Add(JwtClaimTypes.BirthDate);
                });

然后您必须在 Program.cs 中为客户端设置策略

  builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();
  builder.Services.AddAuthorizationCore(options => options.AddPolicy("AtLeast18", policy => policy.Requirements.Add(new MinimumAgeRequirement(18)));

然后您可以在您的页面上使用[授权]属性。

@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy="AtLeast18")]
@page "/adults"

<h3>Adults Only</h3>


政策类:

  public class MinimumAgeRequirement : IAuthorizationRequirement
    {
        public int MinimumAge { get; }

        public MinimumAgeRequirement(int minimumAge)
        {
            MinimumAge = minimumAge;
        }
    }

   public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
    {
        public MinimumAgeHandler(IDateTimeBroker dateTimeBroker)
        {
            DateTimeBroker = dateTimeBroker;
        }

        protected IDateTimeBroker DateTimeBroker { get; }

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MinimumAgeRequirement requirement)
        {

            if (!context.User.HasClaim(c => c.Type == JwtClaimTypes.BirthDate))
            {
                return Task.CompletedTask;
            }
            var claimValue = context.User.FindFirst(c => c.Type == JwtClaimTypes.BirthDate).Value;
            var dob = JsonSerializer.Deserialize<DateTimeOffset?>(claimValue);
            if (!dob.HasValue)
            {
                return Task.CompletedTask;
            }

            var dateOfBirth = dob.Value;


            int calculatedAge = DateTimeBroker.GetDateTime().Date.Year - dateOfBirth.Year;

            if (dateOfBirth > DateTimeBroker.GetDateTime().AddYears(-calculatedAge))
            {
                calculatedAge--;
            }

            if (calculatedAge >= requirement.MinimumAge)
            {
                context.Succeed(requirement);
            }

            return Task.CompletedTask;
        }
    }