自定义 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_name
和 family_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.Register
的 POST
方法中,我添加了:
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>();
我使用的是 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_name
和 family_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.Register
的 POST
方法中,我添加了:
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>();