ASP.NET Identity 和 Claims

39

我正试图摆脱WebForms并学习MVC,特别是使用新的ASP.NET Identity模型。然而,我似乎找不到来自Microsoft的任何正式文档,演示如何创建声明对象,并将其存储在数据库中以进行身份验证。

我的网站需要执行以下操作:

  1. 验证用户 - 已完成
  2. 创建声明,并在其中存储用户信息,以便我可以在整个会话期间使用它 - 未完成
  3. 从新的ASP.NET角色表中检索用户角色 - 未完成

有人能否解释如何实现这一点?


一个很好的关于.NET Core中声明和身份验证的解释 :https://andrewlock.net/introduction-to-authentication-with-asp-net-core/(非本人) - PaulCo
2个回答

105

说实话,我自己对身份验证还在学习过程中。诚然,微软提供的文档可能会更好一些,但我从来没有发现他们的任何文档真正有用。最好的资料总是来自社区,不幸的是,身份验证仍然很新,因此社区尚未真正完善它。

话虽如此,以下是我所知道的,理解其中可能还有更好的方法,只是我还不知道而已。

声明

您的 UserManager 有三种重要的方法:GetClaimsAsyncAddClaimAsyncRemoveClaimAsync

要获取用户所有声明:

var claims = await UserManager.GetClaimsAsync(userId);

您可以通过以下方式获取当前用户的ID:

var userId = User.Identity.GetUserId();

一旦您拥有了索赔,要提取特定的索赔:

var someClaim = claims.FirstOrDefault(c => c.Type == "SomeClaimType");

“SomeClaimType”是添加时声明的名称。在某些情况下,它可能是完全限定的 URN,或者只是一个简单的字符串。如果这不是您个人添加的内容,则最好在调试会话期间检查claims变量以查看实际所拥有的内容。

另外,由于声明列表是可查询的,因此您可以在其上执行任何 LINQ 查询,例如 WhereCount 等等。

要添加新的声明:

await UserManager.AddClaimAsync(userId, new Claim("SomeClaimType", claimValue));

取消索赔的方法:

await UserManager.RemoveClaimAsync(userId, someClaim);

角色

角色的工作方式类似。要获取用户所有的角色:

var roles = await UserManager.GetRolesAsync(userId);

要查看用户是否具有特定角色:

var hasRole = await UserManager.IsInRoleAsync(userId, "SomeRole");

将用户添加到特定角色:

await UserManager.AddToRoleAsync(userId, "SomeRole");

并将其移除:

await UserManager.RemoveFromRoleAsync(userId, "SomeRole");

首先添加角色有一些不同之处;您需要创建 RoleStore 的实例。

var roleStore = new RoleStore<IdentityRole>(context);

然后,您可以使用它来管理所有角色。例如,要创建新角色:

await roleStore.CreateAsync(new IdentityRole("RoleName"));

去掉:

var identityRole = await roleStore.FindByNameAsync("RoleName");
await roleStore.DeleteAsync(identityRole);

目前使用身份特定的API不可能获取所有角色,但您始终可以回退到直接使用Entity Framework查询:

var allRoles = context.Roles.OrderBy(o => o.Name);

1
哇,谢谢Chris。我的假设是,用户通过身份验证后创建一个声明。我是否正确地将其视为该用户的某种会话/通行证?因此,用户登录成功后,根据他们的设置建立一个声明,这些设置需要从数据库中获取。或者,我完全错了吗? - CSharpNewBee
1
有点类似。声明是持久的,因此这不是每次登录都需要构建的内容。声明最好被视为存储短暂信息的一种方式,该信息可能并不适用于每个用户,或者其他方面并不适合实际放在用户表中。存储Facebook身份验证令牌将是正确使用声明的一个很好示例。但是,在这种情况下,一旦用户使用Facebook登录并保存了声明,您可以随时从声明中获取其身份验证令牌。您不必保持添加它。 - Chris Pratt
为什么我没早点发现这篇文章呢?你帮我解决了一个困扰我数周的问题。 - Prescient
1
是的,我理解这一点,但我的情况是有些用户会有相同的声明,比如“ApprovePurchaseOrder”、“ApproveSalesOrder”、“Refund”等。现在我不想硬编码这些字符串,所以我想我必须自己存储它们,并在创建用户时分配这些声明,然后根据这些声明验证用户操作。 - Ali Umair
你只需要“硬编码”它们一次。你可以把它们放在一个静态类中,然后在其他地方强类型引用它们。 - Chris Pratt
显示剩余3条评论

6
关于Asp.Net身份认证,我强烈推荐Brock Allen的实现,称为“Identity Reboot”。 Identity Reboot实际上是ASP.NET身份认证的一组扩展。它受到了对ASP.NET身份认证实现的沮丧启发。
你可以在这里阅读介绍性文章(链接)。您可以从GitHub(链接)下载源代码和样例。
您可以使用Nuget进行安装。
www.nuget.org/packages/BrockAllen.IdentityReboot/
www.nuget.org/packages/BrockAllen.IdentityReboot.Ef/   (for entity framework)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接