这篇文章可能很长,但会有答案所需的所有相关细节。
我一直在搜索,并发现许多其他人也有,以便为HttpContext用户添加声明的正确方法,以便在需要时可以使用Razor在视图中检索这些声明。
例如,
在默认的Asp.Net Core 2.0 Web应用程序中,_LoginPartial具有显示用户电子邮件的代码。如果我想将其更改为用户全名(这假定注册过程包括名字和姓氏条目,并对ApplicationUser类进行适当的更改)
// Add profile data for application users by adding properties to the ApplicationUser class
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public Gender Gender { get; set; }
...balance of code removed for brevity
}
我想在用户上添加一个声明,要求使用他们的全名和性别,而不是默认应用中当前使用的UserManager方法。 (还有其他人在路上)
当前的默认Web应用程序代码
@if (SignInManager.IsSignedIn(User))
{
}
else
{
...code removed for brevity
}
我希望完成的事情;替换这个,
Hello @UserManager.GetUserName(User)!
有了这个
Hello @((ClaimsIdentity) User.Identity).GetSpecificClaim("avatarUrl")!
注意:GetSpecificClaim是一种检索声明的扩展方法。
我认为添加声明的最佳位置是登录方法。
public async Task Login(LoginViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (!ModelState.IsValid) return View(model);
// Now model is valid, require the user to have a confirmed email before they can log on.
var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null)
{
if (!await _userManager.IsEmailConfirmedAsync(user))
{
ModelState.AddModelError(string.Empty,
"You must have a confirmed email to log in.");
return View(model);
}
}
else
{
ModelState.AddModelError(string.Empty,
"There is no registered account for the email address supplied.");
return View(model);
}
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
_logger.LogInformation("User logged in.");
// Add claims to signed in user
var userClaims = HttpContext.User.Claims.ToList();
userClaims.Add(new Claim("fullname", user.GetFullName(user.UserName)));
userClaims.Add(new Claim("avatarUrl", user.AvatarUrl));
// Using ClaimsTransformer
// Add claims here for the logged in user using AddUserInfoClaimsAsync extension method
**var ct = new ClaimsHelpers.ClaimsTransformer();
var identityWithInfoClaims = await ct.AddUserInfoClaimsAsync(User, user);**
return RedirectToLocal(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToAction(nameof(LoginWith2Fa), new { returnUrl, model.RememberMe });
}
if (result.IsLockedOut)
{
_logger.LogWarning("User account locked out.");
return RedirectToAction(nameof(Lockout));
}
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
但userClaims变量始终为空
问题:
- 为什么索赔刚刚设定时索赔清单是空的?
- 是否有不同类型的身份声明?
- 这样做有更好的方法吗?
更新:我在一些早期的尝试中放了一个ClaimsTransformer,我可以使用它添加声明(请参阅登录控制器代码中的粗体更改)但是我现在对ClaimsPrincipal变量identityWithinfoClaims做了什么?我不能将User设置为等于它,因为User是readonly所以这个添加了声明的对象如何被恰当地使用?