如何限制对用户属性的页面访问
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;
}
}
我有一个 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;
}
}