自定义 ASP.NET 身份

Customizing ASP.NET Identity

我使用的是 Identity Server 4,我已经自定义了我的 ASP.NET 身份用户,如下所示:

public class ApplicationUser : IdentityUser
{
    [MaxLength(100)]
    public virtual string FirstName { get; set; }

    [MaxLength(100)]
    public virtual string LastName { get; set; }
}

我看不到要在何处配置 Identity Server 4 以将这 2 个属性包含在声明集合中。我浏览了一些 Identity Server 4 示例,但看不到任何示例。

理想情况下,我想将这 2 个用户属性映射到 given_namefamily_name 声明。

我目前正在连接通知并查询 userinfo 端点(混合流?)。所以我不确定这是身份服务器的配置还是 userinfo 端点的自定义?

这是我所做的:在 AccountController.ExternalLoginCallback 我添加了这个:

//Add claim even if client didn't ask for it
additionalClaims.Add(new Claim(JwtClaimTypes.Email, "email@email.com"));

然后我通过依赖注入 ProfileService class 并在 MyProfileService.GetProfileDataAsync 中添加声明,将声明添加到 access_token 中,如下所示:

public Task GetProfileDataAsync(ProfileDataRequestContext context)
{
    var claims = new List<Claim>();

    Claim emailClaim = context.Subject.Claims.Where<Claim>(claim => claim.Type.Equals(JwtClaimTypes.Email)).FirstOrDefault();

    if (emailClaim != null)
    {
        claims.Add(emailClaim);
    }

    context.IssuedClaims = claims;
    return Task.FromResult(0);
}

我想知道为什么没有这方面的文档。这让我意识到我可能做错了。

我没有看到 table AspNetUserClaims 作为 ASP.NET 身份的一部分创建。我将我的索赔数据添加到此处,索赔数据作为 profile.

的一部分通过

AccountController.RegisterPOST 方法中,我添加了:

var givenNameClaim = new IdentityUserClaim<string>()
{
    ClaimType = "given_name",
    ClaimValue = model.FirstName
};

var familyNameClaim = new IdentityUserClaim<string>()
{
    ClaimType = "family_name",
    ClaimValue = model.LastName
};

var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
user.Claims.Add(givenNameClaim);
user.Claims.Add(familyNameClaim);

为了包含您的自定义声明,您需要使用 IProfileService 实现您自己的 GetProfileDataAsync() 方法。每次请求用户声明时都会调用此方法。

这是我对 IProfileService 的实现。

public class CustomProfileService : IProfileService
{
    private readonly UserManager<User> _userManager;

    public CustomProfileService(UserManager<User> userManager)
    {
        _userManager = userManager;
    }

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var subjectId = context.Subject.GetSubjectId();
        var user = await _userManager.FindByIdAsync(subjectId);

        if (user == null) return;

        var claims = new List<Claim>
        {
            new Claim("username", user.UserName),
            new Claim("email", user.Email),
            new Claim("firstname", user.FirstName),
            new Claim("lastname", user.LastName)
        };

        var roles = await _userManager.GetRolesAsync(user);
        foreach (var role in roles)
        {
            claims.Add(new Claim("role", role));
        }

        var userClaims = await _userManager.GetClaimsAsync(user);
        foreach (var userClaim in userClaims)
        {
            claims.Add(new Claim(userClaim.Type, userClaim.Value));
        }

        context.IssuedClaims = claims;
    }

    public async Task IsActiveAsync(IsActiveContext context)
    {
        var user = await _userManager.FindByIdAsync(context.Subject.GetSubjectId());
        context.IsActive = user.IsActive;
    }
}

然后您必须将以下行添加到 Startup.ConfigureServices()

services.AddScoped<IProfileService, CustomProfileService>();