gpt4 book ai didi

c# - 使用 OWIN Identity v2 Claims 跟踪 WebAPI2 应用程序中的自定义属性

转载 作者:太空狗 更新时间:2023-10-30 01:04:00 25 4
gpt4 key购买 nike

让我全神贯注于新的身份框架,并试图弄清楚如何最好地处理自定义用户属性。我已经尝试扩展 IdentityUser,它用于存储信息,但到目前为止需要额外的数据库调用才能恢复属性。我正在考虑改用声明来存储/检索此信息。

首先,我要存储/检索的特定 prop 不是单个用户所独有的(多对一)。考虑在自定义组结构中将用户分组在一起。我想存储 GroupId 以便在其他相关实体中使用。

我能够存储 GroupId(目前使用 ClaimTypes.NameIdentifier,我认为它不是该类型的正确用法,但是...)。但是,当我去检索该值时,在声明集合中找不到声明类型。它在数据库中,所以我知道它在那里。我错过了一些东西。

FWIW:因为它是 WebAPI,所以我没有使用传统的登录方式。我正在使用 token 授权。

当我创建用户时,我有类似的东西:

public async Task<IdentityResult> CreateUserAsync(string email, string password, string groupId)
{
var userId = ObjectId.GenerateNewId(DateTime.UtcNow).ToString(); // yes, it's a NoSQL store
var user = new ApplicationUser
{
Id = userId,
UserName = email
};

var claim = new IdentityUserClaim { ClaimType = ClaimTypes.NameIdentifier, ClaimValue = groupId, UserId = userId, Id = ObjectId.GenerateNewId(DateTime.UtcNow).ToString() };
user.Claims.Add(claim);

var result = await _UserManager.CreateAsync(user, password);
return result;
}

这会创建一个看起来合适的数据库条目。

当我检索值时,出现空引用错误。这是通过扩展方法编写的代码:

public static string GetGroupId(this IIdentity identity)
{
var claimsIdentity = identity as ClaimsIdentity;
return claimsIdentity == null ? "" : claimsIdentity.FindFirst(ClaimTypes.NameIdentifier).Value;
}

尝试获取值时发生错误,因为 FindFirst 返回空值。

如有任何提示或更好/最佳实践,我们将不胜感激!老实说,我更愿意将它存储在 ApplicationUser : IdentityUser 对象上,但我找不到一种简单的方法来检索 User.Identity 在我的 api Controller 上下文中,而无需额外调用数据库。

最佳答案

您关于将额外数据存储为声明的直觉是正确的,但实现起来有点问题。

我建议为您的域信息创建您自己的声明类型。不要重用框架提供的声明类型。原因是 ClaimTypes.NameIdentifier 代表 User.Id。该框架本身为所有用户添加了标准声明列表:

  • User.Id => 表示为 ClaimTypes.NameIdentifier
  • 用户名 => 表示为“ClaimTypes.Name”
  • ProviderName => 表示为 ClaimTypes.ProviderName(对此不是 100% 确定);通常值为“ASP.NET Identity”
  • SecurityStamp 值(不确定它的声明类型名称是什么)
  • 分配给用户的所有角色都存储为 ClaimTypes.Role

因此,在您的情况下,您尝试用 User.Id 的值覆盖声明,这非常重要,我认为 -)

现在,让我们尝试解决您的编码问题。创建用户时,在创建用户对象后添加声明:

public async Task<IdentityResult> CreateUserAsync(string email, string password, string groupId)
{
var user = new ApplicationUser
{
Id = userId,
UserName = email
};

var userCreateResult = await _UserManager.CreateAsync(user, password);
if(!userCreateResult.IsSuccess)
{
// user creation have failed - need to stop the transaction
return userCreateResult;
}

// better to have a class with constants representing your claim types
var groupIdClaim = new Claim("MyApplication:GroupClaim", ObjectId.GenerateNewId(DateTime.UtcNow).ToString());

// this will save the claim into the database. Next time user logs in, it will be added to Principal.Identity
var claimAddingResult = await _UserManager.AddClaimAsync(userId, groupIdClaim);
return claimAddingResult;
}

至于扩展方法,我通常使用 IPrincipalClaimsPrincipal。但是 IIdentity 也是可行的。不要忘记,您可以通过调用 ClaimsPrincipal.Current 在任何地方访问 ClaimsPrincipal

这就是我通常使用扩展方法的方式:

public static string GetGroupId(this ClaimsPrincipal principal)
{
var groupIdClaim = principal.Claims.FirstOrDefault(c => c.Type == "MyApplication:GroupClaim");
if (personIdClaim != null)
{
return groupIdClaim.Value;
}
return String.Empty;
}

因此在您的方法中,您会像这样为当前登录的用户检索分配的 groupId:

var groupId = ClaimsPrincipal.Current.GetGroupId();

希望这能澄清您的困惑!

关于c# - 使用 OWIN Identity v2 Claims 跟踪 WebAPI2 应用程序中的自定义属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25328717/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com