我有一个blazor页面,需要按年龄限制访问。我正在使用托管的Web程序集。我想使用[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;
}
}