c# - 为 Identity User 自定义属性实现 get/set 方法
问题描述
我正在使用 Identity,并使用三个自定义属性扩展了基本 IdentityUser。使用 .netCore 3.1.1 和身份 4
namespace FleetLogix.Intranet.Identity
{
// Add profile data for application users by adding properties to the ApplicationUser class
public class ApplicationUser : IdentityUser<int>
{
[MaxLength(50)]
[PersonalData]
public string FirstName { get; set; }
[MaxLength(50)]
[PersonalData]
public string LastName { get; set; }
[MaxLength(5)]
public string OrgCode { get; set; }
public ApplicationUser() : base()
{
}
}
}
这些是在[AspNetUsers]
表中愉快地创建的。已创建 4 个初始用户,并填充了所有其他属性。
我还创建了一些扩展,让我可以获取这些属性的值。FirstName -> GivenName, LastName -> Surname 和 OrgCode 是 CustomClaimTypes.OrgCode
namespace FleetLogix.Intranet.Identity
{
/// <summary>
/// Extends the <see cref="System.Security.Principal.IIdentity" /> object to add accessors for our custom properties.
/// </summary>
public static class IdentityExtensions
{
/// <summary>
/// Gets the value of the custom user property FirstName
/// </summary>
/// <example>
/// User.Identity.GetFirstName()
/// </example>
/// <param name="identity">Usually the Identity of the current logged in User</param>
/// <returns><see langword="string"/> containing value of LastName or an empty string</returns>
public static string GetFirstName(this IIdentity identity)
{
ClaimsIdentity claimsIdentity = identity as ClaimsIdentity;
Claim claim = claimsIdentity?.FindFirst(ClaimTypes.GivenName);
return claim?.Value ?? string.Empty;
}
/// <summary>
/// Gets the value of the custom user property LastName
/// </summary>
/// <example>
/// User.Identity.GetLastName()
/// </example>
/// <param name="identity">Usually the Identity of the current logged in User</param>
/// <returns><see langword="string"/> containing value of LastName or an empty string</returns>
public static string GetLastName(this IIdentity identity)
{
ClaimsIdentity claimsIdentity = identity as ClaimsIdentity;
Claim claim = claimsIdentity?.FindFirst(ClaimTypes.Surname);
return claim?.Value ?? string.Empty;
}
/// <summary>
/// Gets the value of the custom user property OrgCode
/// </summary>
/// <example>
/// User.Identity.GetOrgCode()
/// </example>
/// <param name="identity">Usually the Identity of the current logged in User</param>
/// <returns><see langword="string"/> containing value of OrgCode or an empty string</returns>
public static string GetOrgCode(this IIdentity identity)
{
ClaimsIdentity claimsIdentity = identity as ClaimsIdentity;
Claim claim = claimsIdentity?.FindFirst(CustomClaimTypes.OrgCode);
return claim?.Value ?? string.Empty;
}
}
}
我正在建立一个新站点并想修改_LoginPartial.cshtml
. 我想用登录的名字替换登录的用户名(电子邮件地址)的显示
@if (SignInManager.IsSignedIn(User))
{
<li class="nav-item">
<a id="manage" class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @UserManager.GetUserName(User)!</a>
</li>
...
}
对此
@if (SignInManager.IsSignedIn(User))
{
<li class="nav-item">
<a id="manage" class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @User.Identity.GetFirstName()!</a>
</li>
...
}
但是,这会导致空文本。 为什么这个是空白的?
点击进入Account/Manage/Index
页面,我会看到一个用于修改用户详细信息的表单。我已修改 InputModel 以包含两个自定义属性(FirstName、LastName)。该LoadAsync
任务已修改为加载值(使用扩展方法)并将它们添加到`InputModel
private async Task LoadAsync(ApplicationUser user)
{
var userName = await _userManager.GetUserNameAsync(user);
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
var firstName = user.FirstName;
var lastName = user.LastName;
var orgCode = user.OrgCode;
Username = userName;
OrgCode = orgCode;
Input = new InputModel
{
PhoneNumber = phoneNumber,
FirstName = firstName,
LastName = lastName
};
}
为什么自定义属性在此页面上可见,但在上一个页面上不可见?
更进一步的Account/Manage/Index
是更新方法OnPostAsync()
public async Task<IActionResult> OnPostAsync()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
if (!ModelState.IsValid)
{
await LoadAsync(user);
return Page();
}
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
if (Input.PhoneNumber != phoneNumber)
{
var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber);
if (!setPhoneResult.Succeeded)
{
var userId = await _userManager.GetUserIdAsync(user);
throw new InvalidOperationException($"Unexpected error occurred setting phone number for user with ID '{userId}'.");
}
}
var firstName = user.FirstName; //.GetPhoneNumberAsync(user);
if (Input.FirstName != firstName)
{
//var setFirstNameResult = await _userManager.SetFirstNameAsync(user, Input.FirstName);
user.FirstName = Input.FirstName;
//if (!setFirstNameResult.Succeeded)
//{
// var userId = await _userManager.GetUserIdAsync(user);
// throw new InvalidOperationException($"Unexpected error occurred setting First Name for user with ID '{userId}'.");
//}
}
var lastName = user.LastName;
if (Input.LastName != lastName)
{
//var setLastNameResult = await _userManager.SetLastNameAsync(user, Input.LastName);
user.LastName = Input.LastName;
//if (!setLastNameResult.Succeeded)
//{
// var userId = await _userManager.GetUserIdAsync(user);
// throw new InvalidOperationException($"Unexpected error occurred setting Last Name for user with ID '{userId}'.");
//}
}
await _signInManager.RefreshSignInAsync(user);
StatusMessage = "Your profile has been updated";
return RedirectToPage();
}
没有像SetPhoneNumberAsync()
我尝试使用属性设置器的 Set 方法。这没有用。 如何更新身份用户自定义属性值?
我只想能够使用自定义用户属性。我需要 FirstName & OrgCode 属性在他们登录后立即可用,目前情况并非如此。当前的扩展方法并不总是有效。
此外,我需要能够编辑这些属性,以防它们出现错误或更改要求。
解决方案
您需要创建身份范围,只需创建您的身份并添加范围
services.AddScoped<IUserIdentity, UserIdentity>();
您需要middleware
在身份中实现映射所有属性。添加到启动:
app.UseMiddleware<UserIdentityAccessor>();
执行:
public class UserIdentityAccessor
{
private readonly RequestDelegate _next;
public UserIdentityAccessor(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context, IUserIdentity userIdentity)
{
var user = (ClaimsIdentity) context.User.Identity;
if (user.IsAuthenticated)
{
var first = user.FindFirst(ClaimsName.FirstName).Value; \\ get info from claims
userIdentity.FirstName = first; \\ and add to identity
}
else
{
userIdentity.FirstName = null;
}
await _next(context);
}
}
现在您可以随心所欲地获得身份
推荐阅读
- excel - 平均 3 个值在 1 列中循环?
- elasticsearch - kibana中数据表组件中的动态列
- python - 数组中的元素将数据类型从浮点数更改为字符串
- c# - WPF如何制作一个自定义组合框,里面有一个按钮来清除
- node.js - 如何在 Firebase 后端运行一些脚本?
- php - PHP if 锚标记语句不起作用
- java - 从消费者组中获取 KafkaConsumers 列表
- python - Pandas - 基于每列的前 x% 值,标记为新数字
- python - 将scipy稀疏coo矩阵转换为networkx图并返回不会产生原始矩阵
- node.js - 无法编译SASS,相对路径~找不到